ortoni-report 1.1.5 → 1.1.7
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/changelog.md +24 -0
- package/dist/css/main.css +22445 -22445
- package/dist/ortoni-report.d.ts +50 -4
- package/dist/ortoni-report.js +149 -118
- package/dist/ortoni-report.mjs +149 -118
- package/dist/report-template.hbs +311 -255
- package/dist/utils/modal.js +10 -3
- package/package.json +3 -2
- package/readme.md +64 -116
package/dist/report-template.hbs
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<meta name="description" content="
|
|
8
|
-
<title>Playwright Test Report</title>
|
|
7
|
+
<meta name="description" content="Playwright HTML report by LetCode Koushik - V1.1.7">
|
|
8
|
+
<title>Ortoni Playwright Test Report</title>
|
|
9
9
|
<link rel="icon" href="node_modules/ortoni-report/dist/icon/32.png" type="image/x-icon">
|
|
10
10
|
<link rel="stylesheet" href="node_modules/ortoni-report/dist/css/main.css">
|
|
11
11
|
</head>
|
|
@@ -13,33 +13,28 @@
|
|
|
13
13
|
#summary, #testDetails, button#back-to-summary {
|
|
14
14
|
transition: opacity 0.2s ease-in-out;
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
.filter.active {
|
|
17
18
|
background-color: var(--bulma-background-active);
|
|
18
19
|
}
|
|
19
|
-
|
|
20
20
|
::-webkit-scrollbar {
|
|
21
|
-
width:
|
|
22
|
-
|
|
21
|
+
width: 8px;
|
|
22
|
+
height: 8px;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
::-webkit-scrollbar-
|
|
26
|
-
background
|
|
27
|
-
;
|
|
28
|
-
border-radius: 0px;
|
|
25
|
+
::-webkit-scrollbar-track {
|
|
26
|
+
background: #f1f1f1;
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
::-webkit-scrollbar-thumb
|
|
32
|
-
background
|
|
33
|
-
;
|
|
29
|
+
::-webkit-scrollbar-thumb {
|
|
30
|
+
background: #888;
|
|
31
|
+
border-radius: 4px;
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
::-webkit-scrollbar-
|
|
37
|
-
background
|
|
34
|
+
::-webkit-scrollbar-thumb:hover {
|
|
35
|
+
background: #555;
|
|
38
36
|
}
|
|
39
37
|
|
|
40
|
-
::-webkit-scrollbar-corner {
|
|
41
|
-
background-color: #fff;
|
|
42
|
-
}
|
|
43
38
|
div#testDetails {
|
|
44
39
|
position: sticky;
|
|
45
40
|
top: 0;
|
|
@@ -74,17 +69,27 @@
|
|
|
74
69
|
details[open] > summary::after {
|
|
75
70
|
transform: rotate(0deg);
|
|
76
71
|
}
|
|
72
|
+
.logoimage{
|
|
73
|
+
max-width: 100px;
|
|
74
|
+
}
|
|
77
75
|
|
|
78
76
|
</style>
|
|
79
77
|
|
|
80
78
|
<body>
|
|
81
|
-
<!-- Header -->
|
|
82
79
|
<section class="section">
|
|
83
80
|
<header class="container">
|
|
84
81
|
<div class="columns is-vcentered">
|
|
85
|
-
<div class="column is-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
<div class="column is-two-fifths">
|
|
83
|
+
<div class="columns is-desktop is-vcentered is-multiline">
|
|
84
|
+
{{#if logo}}
|
|
85
|
+
<div class="column-1">
|
|
86
|
+
<figure class="image logoimage">
|
|
87
|
+
<img src="{{logo}}" />
|
|
88
|
+
</figure>
|
|
89
|
+
</div>
|
|
90
|
+
{{/if}}
|
|
91
|
+
{{#if projectName}}<div class="column"><span class="title">{{projectName}}</span></div>{{/if}}
|
|
92
|
+
</div>
|
|
88
93
|
</div>
|
|
89
94
|
<div class="column">
|
|
90
95
|
<div class="control">
|
|
@@ -99,13 +104,11 @@
|
|
|
99
104
|
</div>
|
|
100
105
|
</header>
|
|
101
106
|
</section>
|
|
102
|
-
|
|
103
|
-
<!-- Main Content -->
|
|
104
107
|
<section class="section">
|
|
105
108
|
<main class="container">
|
|
106
109
|
<div class="columns">
|
|
107
|
-
<aside class="column is-
|
|
108
|
-
<div class="columns">
|
|
110
|
+
<aside class="column is-two-fifths">
|
|
111
|
+
<div class="columns is-mobile">
|
|
109
112
|
<div class="column">
|
|
110
113
|
<h2 class="title is-4">Tests</h2>
|
|
111
114
|
</div>
|
|
@@ -120,7 +123,7 @@
|
|
|
120
123
|
</div>
|
|
121
124
|
</div>
|
|
122
125
|
</div>
|
|
123
|
-
<div class="content">
|
|
126
|
+
<div class="content sidebar">
|
|
124
127
|
{{#each groupedResults}}
|
|
125
128
|
<details class="box">
|
|
126
129
|
<summary class="is-size-5 has-icon-right">
|
|
@@ -133,8 +136,8 @@
|
|
|
133
136
|
</summary>
|
|
134
137
|
<ul>
|
|
135
138
|
{{#each this}}
|
|
136
|
-
<details>
|
|
137
|
-
<summary class="is-size-5">
|
|
139
|
+
<details class="mt-1">
|
|
140
|
+
<summary class="is-size-5 is-capitalized">
|
|
138
141
|
<div class="icon-text">
|
|
139
142
|
<span class="icon has-text-info">
|
|
140
143
|
<img class="image is-16x16" src="node_modules/ortoni-report/dist/icon/test.png" alt="test name">
|
|
@@ -144,11 +147,12 @@
|
|
|
144
147
|
</summary>
|
|
145
148
|
<ul>
|
|
146
149
|
{{#each this}}
|
|
147
|
-
<details>
|
|
148
|
-
<summary>{{@key}}</summary>
|
|
150
|
+
<details class="mb-1">
|
|
151
|
+
<summary class="is-capitalized is-size-6">{{@key}}</summary>
|
|
149
152
|
<ul>
|
|
150
153
|
{{#each this}}
|
|
151
154
|
<li class="media" data-suite-name="{{suite}}"
|
|
155
|
+
data-test-duration="{{duration}}"
|
|
152
156
|
data-project-name="{{projectName}}" data-test-id="{{index}}"
|
|
153
157
|
data-test-status="{{status}} {{retry}}">
|
|
154
158
|
<div class="icon-text">
|
|
@@ -201,8 +205,7 @@
|
|
|
201
205
|
{{/each}}
|
|
202
206
|
</div>
|
|
203
207
|
</aside>
|
|
204
|
-
|
|
205
|
-
<section class="column">
|
|
208
|
+
<section class="column is-three-fifths">
|
|
206
209
|
{{!-- Overall summary --}}
|
|
207
210
|
<div id="summary">
|
|
208
211
|
<div class="columns is-multiline">
|
|
@@ -304,6 +307,7 @@
|
|
|
304
307
|
<div id="testDetails" style="display: none;">
|
|
305
308
|
<!-- Back button should be outside the dynamic content -->
|
|
306
309
|
<button class="button content" id="back-to-summary"onclick="showSummary()">Back to Summary</button>
|
|
310
|
+
<div class="tags" id="attachTags"></div>
|
|
307
311
|
<!-- Test Details will be displayed here -->
|
|
308
312
|
</div>
|
|
309
313
|
</section>
|
|
@@ -325,53 +329,63 @@
|
|
|
325
329
|
});
|
|
326
330
|
}
|
|
327
331
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const themeButton = document.getElementById("toggle-theme");
|
|
335
|
-
const preferredTheme = themeButton.getAttribute("data-theme-status");
|
|
336
|
-
const htmlElement = document.documentElement;
|
|
337
|
-
|
|
338
|
-
if (preferredTheme === 'dark') {
|
|
339
|
-
htmlElement.setAttribute('data-theme', 'dark');
|
|
340
|
-
themeButton.classList.add('is-dark');
|
|
341
|
-
themeButton.textContent = 'Dark';
|
|
342
|
-
} else if (preferredTheme === 'light') {
|
|
343
|
-
htmlElement.setAttribute('data-theme', 'light');
|
|
344
|
-
themeButton.classList.add('is-light');
|
|
345
|
-
themeButton.textContent = 'Light';
|
|
346
|
-
}
|
|
332
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
333
|
+
const testData = {{{ json results }}};
|
|
334
|
+
const testDetails = document.getElementById('testDetails');
|
|
335
|
+
const summary = document.getElementById('summary');
|
|
336
|
+
const backButton = document.querySelector('button#back-to-summary');
|
|
347
337
|
|
|
348
|
-
|
|
349
|
-
const
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
if (
|
|
353
|
-
|
|
338
|
+
const themeButton = document.getElementById("toggle-theme");
|
|
339
|
+
const preferredTheme = themeButton.getAttribute("data-theme-status");
|
|
340
|
+
const htmlElement = document.documentElement;
|
|
341
|
+
|
|
342
|
+
if (preferredTheme === 'dark') {
|
|
343
|
+
htmlElement.setAttribute('data-theme', 'dark');
|
|
354
344
|
themeButton.classList.add('is-dark');
|
|
355
345
|
themeButton.textContent = 'Dark';
|
|
356
|
-
} else {
|
|
357
|
-
|
|
346
|
+
} else if (preferredTheme === 'light') {
|
|
347
|
+
htmlElement.setAttribute('data-theme', 'light');
|
|
358
348
|
themeButton.classList.add('is-light');
|
|
359
349
|
themeButton.textContent = 'Light';
|
|
360
350
|
}
|
|
361
|
-
});
|
|
362
351
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
352
|
+
themeButton.addEventListener('click', () => {
|
|
353
|
+
const currentTheme = htmlElement.getAttribute('data-theme');
|
|
354
|
+
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
|
|
355
|
+
htmlElement.setAttribute('data-theme', newTheme);
|
|
356
|
+
if (newTheme === 'dark') {
|
|
357
|
+
themeButton.classList.remove('is-light');
|
|
358
|
+
themeButton.classList.add('is-dark');
|
|
359
|
+
themeButton.textContent = 'Dark';
|
|
360
|
+
} else {
|
|
361
|
+
themeButton.classList.remove('is-dark');
|
|
362
|
+
themeButton.classList.add('is-light');
|
|
363
|
+
themeButton.textContent = 'Light';
|
|
364
|
+
}
|
|
365
|
+
});
|
|
368
366
|
|
|
369
|
-
|
|
367
|
+
function showSummary() {
|
|
368
|
+
summary.style.display = 'block';
|
|
369
|
+
testDetails.style.display = 'none';
|
|
370
|
+
backButton.style.display = 'none';
|
|
371
|
+
}
|
|
370
372
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
373
|
+
window.showSummary = showSummary;
|
|
374
|
+
|
|
375
|
+
function attachTags(testTags){
|
|
376
|
+
const tags = document.querySelector("#attachTags");
|
|
377
|
+
testTags.forEach(tag => {
|
|
378
|
+
const tagElement = document.createElement('span');
|
|
379
|
+
tagElement.className = 'tag is-info';
|
|
380
|
+
tagElement.textContent = tag;
|
|
381
|
+
tags.appendChild(tagElement);
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function displayTestDetails(test) {
|
|
386
|
+
const summary = document.getElementById('summary');
|
|
387
|
+
const testDetails = document.getElementById('testDetails');
|
|
388
|
+
const backButton = document.querySelector('button#back-to-summary');
|
|
375
389
|
summary.style.display = 'none';
|
|
376
390
|
testDetails.style.opacity = '0';
|
|
377
391
|
testDetails.style.display = 'block';
|
|
@@ -379,218 +393,260 @@
|
|
|
379
393
|
testDetails.style.opacity = '1';
|
|
380
394
|
backButton.style.opacity = '1';
|
|
381
395
|
}, 50);
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
let statusClass = '';
|
|
385
|
-
let statusText = test.status.toUpperCase();
|
|
386
|
-
if (test.status.startsWith('passed')) {
|
|
387
|
-
statusClass = 'tag is-success';
|
|
388
|
-
} else if (test.status === 'flaky') {
|
|
389
|
-
statusClass = 'tag is-warning';
|
|
390
|
-
} else if (test.status === 'failed') {
|
|
391
|
-
statusClass = 'tag is-danger';
|
|
392
|
-
} else {
|
|
393
|
-
statusClass = 'tag is-info';
|
|
394
|
-
}
|
|
395
396
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
397
|
+
let statusClass = '';
|
|
398
|
+
let statusText = test.status.toUpperCase();
|
|
399
|
+
if (test.status.startsWith('passed')) {
|
|
400
|
+
statusClass = 'tag is-success';
|
|
401
|
+
} else if (test.status === 'flaky') {
|
|
402
|
+
statusClass = 'tag is-warning';
|
|
403
|
+
} else if (test.status === 'failed') {
|
|
404
|
+
statusClass = 'tag is-danger';
|
|
405
|
+
} else {
|
|
406
|
+
statusClass = 'tag is-info';
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
testDetails.innerHTML = `
|
|
410
|
+
<button class="button content" id="back-to-summary" style="display: block" onclick="showSummary()">Back to Summary</button>
|
|
411
|
+
<div class="content has-text-centered">
|
|
412
|
+
<p class="title">${test.title}</p>
|
|
413
|
+
<p class="subtitle" id="filepath">${test.location}</p>
|
|
406
414
|
</div>
|
|
407
|
-
<div class="
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
<
|
|
415
|
+
<div class="columns">
|
|
416
|
+
<div class="column content">
|
|
417
|
+
<h4 class="title is-4">Status</h4>
|
|
418
|
+
<p class="${statusClass}">${statusText}</p>
|
|
419
|
+
${test.duration.length > 0 ? `
|
|
420
|
+
<h4 class="title is-4">Duration</h4>
|
|
421
|
+
<p class="${statusClass}">${test.duration}</p>` : ""}
|
|
422
|
+
<div class="tags" id="attachTags"></div>
|
|
423
|
+
${test.videoPath ? `
|
|
424
|
+
<div id="testVideo" class="modal">
|
|
425
|
+
<div class="modal-background"></div>
|
|
426
|
+
<div class="modal-content">
|
|
427
|
+
<figure>
|
|
428
|
+
<video controls>
|
|
429
|
+
<source src="file://${test.videoPath}" type="video/webm">
|
|
430
|
+
Your browser does not support the video tag.
|
|
431
|
+
</video>
|
|
432
|
+
</figure>
|
|
433
|
+
</div>
|
|
434
|
+
<button onclick="closeVideo()" class="modal-close is-large" aria-label="close"></button>
|
|
435
|
+
</div>
|
|
436
|
+
<button class="button" onclick="openVideo()">Attachment: Video</button>
|
|
437
|
+
`:''}
|
|
438
|
+
</div>
|
|
439
|
+
<div class="column content">
|
|
440
|
+
${test.screenshotPath ? `
|
|
441
|
+
<div id="testImage" class="modal">
|
|
442
|
+
<div class="modal-background"></div>
|
|
411
443
|
<div class="modal-content">
|
|
412
|
-
<p class="image
|
|
413
|
-
|
|
444
|
+
<p class="image">
|
|
445
|
+
<img src="${test.base64Image ? test.screenshotPath : `file://${test.screenshotPath}`}" alt="Screenshot">
|
|
414
446
|
</p>
|
|
415
447
|
</div>
|
|
416
|
-
|
|
448
|
+
<button onclick="closeModal()" class="modal-close is-large" aria-label="close"></button>
|
|
449
|
+
</div>
|
|
450
|
+
<figure class="image box">
|
|
451
|
+
<img onclick="openModal()" src="${test.base64Image ? test.screenshotPath : `file://${test.screenshotPath}`}" alt="Screenshot">
|
|
452
|
+
</figure>` : ''}
|
|
417
453
|
</div>
|
|
418
|
-
<figure class="image is-16by9">
|
|
419
|
-
<img onclick="openModal()" src="data:image/png;base64, ${test.screenshotPath}" alt="Screenshot">
|
|
420
|
-
</figure>` : ''}
|
|
421
454
|
</div>
|
|
422
|
-
</div>
|
|
423
|
-
<div class="content">
|
|
424
|
-
${test.steps.length > 0 ? `
|
|
425
|
-
<details id="stepopen">
|
|
426
|
-
<summary><h4 class="title is-4">Steps</h4></summary>
|
|
427
|
-
<span id="stepDetails" class="content"></span>
|
|
428
|
-
</details>
|
|
429
|
-
`: ``}
|
|
430
|
-
</div class="content">
|
|
431
|
-
<div>
|
|
432
|
-
${test.errors.length ? `
|
|
433
|
-
<h4 class="title is-4">Errors</h4>
|
|
434
455
|
<div class="content">
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
456
|
+
${test.steps.length > 0 ? `
|
|
457
|
+
<details id="stepopen">
|
|
458
|
+
<summary><h4 class="title is-4">Steps</h4></summary>
|
|
459
|
+
<span id="stepDetails" class="content"></span>
|
|
460
|
+
</details>
|
|
461
|
+
`: ``}
|
|
462
|
+
</div class="content">
|
|
463
|
+
<div>
|
|
464
|
+
${test.errors.length ? `
|
|
465
|
+
<h4 class="title is-4">Errors</h4>
|
|
466
|
+
<div class="content">
|
|
467
|
+
<pre><code class="data-lang=js">${escapeHtml(test.errors.join('\n'))}</code></pre>
|
|
468
|
+
</div>` : ''}
|
|
469
|
+
</div>
|
|
470
|
+
<div>
|
|
471
|
+
${test.logs ? `
|
|
472
|
+
<h4 class="title is-4">Logs</h4>
|
|
473
|
+
<div class="box">
|
|
474
|
+
<pre>${escapeHtml(test.logs)}</pre>
|
|
475
|
+
</div>` : ''}
|
|
476
|
+
</div>
|
|
477
|
+
`;
|
|
478
|
+
|
|
479
|
+
const stepDetailsDiv = document.getElementById('stepDetails');
|
|
480
|
+
if(stepDetailsDiv){
|
|
481
|
+
const stepsList = attachSteps(test);
|
|
482
|
+
const detail = document.getElementById("stepopen");
|
|
483
|
+
if(test.errors.length > 0){
|
|
484
|
+
detail.setAttribute("open", "");
|
|
485
|
+
}
|
|
486
|
+
stepDetailsDiv.appendChild(stepsList);
|
|
487
|
+
}
|
|
488
|
+
attachTags(test.testTags);
|
|
453
489
|
}
|
|
454
|
-
}
|
|
455
490
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
const test = testData[testId];
|
|
474
|
-
displayTestDetails(test);
|
|
491
|
+
function attachSteps(test) {
|
|
492
|
+
const stepsList = document.createElement("ul");
|
|
493
|
+
stepsList.setAttribute("id", "steps");
|
|
494
|
+
stepsList.innerHTML = '';
|
|
495
|
+
test.steps.forEach(step => {
|
|
496
|
+
const li = document.createElement('li');
|
|
497
|
+
li.innerHTML = `<strong class="${step.snippet ? 'has-text-danger' : ''}">${step.title}</strong>`;
|
|
498
|
+
if (step.snippet) {
|
|
499
|
+
const pre = document.createElement('pre');
|
|
500
|
+
const code = document.createElement('code');
|
|
501
|
+
const locationText = step.location ? `\n\nat: ${step.location}` : '';
|
|
502
|
+
code.textContent = `${step.snippet}${locationText}`;
|
|
503
|
+
code.setAttribute('data-lang', 'js');
|
|
504
|
+
pre.appendChild(code);
|
|
505
|
+
li.appendChild(pre);
|
|
506
|
+
}
|
|
507
|
+
stepsList.appendChild(li);
|
|
475
508
|
});
|
|
476
|
-
|
|
509
|
+
return stepsList;
|
|
510
|
+
}
|
|
477
511
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
}
|
|
512
|
+
|
|
513
|
+
function attachEventListeners() {
|
|
514
|
+
const testItems = document.querySelectorAll('[data-test-id]');
|
|
515
|
+
testItems.forEach(item => {
|
|
516
|
+
item.addEventListener('click', () => {
|
|
517
|
+
const testId = item.getAttribute('data-test-id');
|
|
518
|
+
const test = testData[testId];
|
|
519
|
+
displayTestDetails(test);
|
|
487
520
|
});
|
|
488
|
-
filter.classList.add('active');
|
|
489
|
-
applyFilters();
|
|
490
521
|
});
|
|
491
|
-
});
|
|
492
522
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
523
|
+
const filters = document.querySelectorAll('.filter');
|
|
524
|
+
filters.forEach(filter => {
|
|
525
|
+
filter.addEventListener('click', () => {
|
|
526
|
+
const status = filter.getAttribute('data-status');
|
|
527
|
+
filters.forEach(f => {
|
|
528
|
+
if (f.getAttribute('data-status')) {
|
|
529
|
+
f.classList.remove('active');
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
filter.classList.add('active');
|
|
533
|
+
applyFilters();
|
|
534
|
+
});
|
|
535
|
+
});
|
|
503
536
|
|
|
504
|
-
|
|
505
|
-
|
|
537
|
+
const projectFilter = document.getElementById('project-filter');
|
|
538
|
+
projectFilter.addEventListener('change', () => {
|
|
539
|
+
applyFilters();
|
|
540
|
+
});
|
|
541
|
+
}
|
|
506
542
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
item.
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
543
|
+
function applyFilters() {
|
|
544
|
+
const selectedProject = document.getElementById('project-filter').value;
|
|
545
|
+
const activeFilter = document.querySelector('.filter.active');
|
|
546
|
+
const selectedStatus = activeFilter ? activeFilter.getAttribute('data-status') : 'all';
|
|
547
|
+
|
|
548
|
+
const testItems = document.querySelectorAll('li[data-test-id]');
|
|
549
|
+
const detailsElements = document.querySelectorAll('details');
|
|
550
|
+
|
|
551
|
+
detailsElements.forEach(details => {
|
|
552
|
+
let shouldShowDetails = false;
|
|
553
|
+
const items = details.querySelectorAll('li[data-test-id]');
|
|
554
|
+
items.forEach(item => {
|
|
555
|
+
const projectName = item.getAttribute('data-project-name').trim();
|
|
556
|
+
const testStatus = item.getAttribute('data-test-status').trim();
|
|
557
|
+
const matchesProject = (selectedProject === 'all' || projectName === selectedProject);
|
|
558
|
+
const matchesStatus = (selectedStatus === 'all' || testStatus.includes(selectedStatus) ||
|
|
559
|
+
(selectedStatus === 'failed' && (testStatus === 'failed' || testStatus === 'timedOut')) ||
|
|
560
|
+
(selectedStatus === 'retry' && testStatus.includes('retry')) ||
|
|
561
|
+
(selectedStatus === 'flaky' && testStatus.includes('flaky')));
|
|
562
|
+
|
|
563
|
+
if (matchesProject && matchesStatus) {
|
|
564
|
+
item.classList.remove('is-hidden');
|
|
565
|
+
shouldShowDetails = true;
|
|
566
|
+
} else {
|
|
567
|
+
item.classList.add('is-hidden');
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
details.open = shouldShowDetails;
|
|
571
|
+
details.classList.toggle('is-hidden', !shouldShowDetails);
|
|
525
572
|
});
|
|
526
|
-
|
|
527
|
-
details.classList.toggle('is-hidden', !shouldShowDetails);
|
|
528
|
-
});
|
|
529
|
-
}
|
|
573
|
+
}
|
|
530
574
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
575
|
+
const searchInput = document.querySelector('input[name="search"]');
|
|
576
|
+
const detailsElements = document.querySelectorAll('details');
|
|
577
|
+
function filterTests(search){
|
|
578
|
+
const searchTerm = search.toLowerCase();
|
|
579
|
+
const testItems = document.querySelectorAll('[data-test-id]');
|
|
536
580
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
581
|
+
if (searchTerm) {
|
|
582
|
+
detailsElements.forEach(detail => {
|
|
583
|
+
detail.open = false; // Collapse all details initially
|
|
584
|
+
});
|
|
541
585
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
586
|
+
testItems.forEach(item => {
|
|
587
|
+
const testTitle = item.textContent.toLowerCase();
|
|
588
|
+
if (testTitle.includes(searchTerm)) {
|
|
589
|
+
item.style.display = 'block'; // Show matching test item
|
|
590
|
+
|
|
591
|
+
let parent = item.parentElement;
|
|
592
|
+
while (parent && parent.tagName !== 'ASIDE') {
|
|
593
|
+
if (parent.tagName === 'DETAILS') {
|
|
594
|
+
parent.open = true;
|
|
595
|
+
}
|
|
596
|
+
parent = parent.parentElement;
|
|
551
597
|
}
|
|
552
|
-
|
|
598
|
+
} else {
|
|
599
|
+
item.style.display = 'none';
|
|
553
600
|
}
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
detail.open = false;
|
|
564
|
-
});
|
|
601
|
+
});
|
|
602
|
+
} else {
|
|
603
|
+
testItems.forEach(item => {
|
|
604
|
+
item.style.display = 'block';
|
|
605
|
+
});
|
|
606
|
+
detailsElements.forEach(detail => {
|
|
607
|
+
detail.open = false;
|
|
608
|
+
});
|
|
609
|
+
}
|
|
565
610
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
611
|
+
function debounce(func, wait) {
|
|
612
|
+
let timeout;
|
|
613
|
+
return function(...args) {
|
|
614
|
+
clearTimeout(timeout);
|
|
615
|
+
timeout = setTimeout(() => func.apply(this, args), wait);
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
const debouncedSearch = debounce((event) => {
|
|
620
|
+
filterTests(event.target.value);
|
|
621
|
+
}, 300);
|
|
622
|
+
|
|
623
|
+
searchInput.addEventListener('input', debouncedSearch);
|
|
624
|
+
|
|
625
|
+
const ctx = document.getElementById('testChart').getContext('2d');
|
|
626
|
+
new Chart(ctx, {
|
|
627
|
+
type: 'doughnut',
|
|
628
|
+
data: {
|
|
629
|
+
labels: ['Passed', 'Failed', 'Skipped','Flaky'],
|
|
630
|
+
datasets: [{
|
|
631
|
+
data: [{{ passCount }}, {{ failCount }}, {{ skipCount }}, {{flakyCount}}],
|
|
632
|
+
backgroundColor: ['#28a745', '#dc3545', '#d5d4a1', '#FFB704']
|
|
633
|
+
}]
|
|
634
|
+
},
|
|
635
|
+
options: {
|
|
636
|
+
responsive: true,
|
|
637
|
+
maintainAspectRatio: false,
|
|
638
|
+
plugins: {
|
|
639
|
+
legend: {
|
|
640
|
+
position: 'right'
|
|
641
|
+
}
|
|
584
642
|
}
|
|
585
643
|
}
|
|
586
|
-
}
|
|
587
|
-
});
|
|
644
|
+
});
|
|
588
645
|
|
|
589
|
-
|
|
590
|
-
});
|
|
646
|
+
attachEventListeners();
|
|
647
|
+
});
|
|
591
648
|
|
|
592
|
-
</script>
|
|
649
|
+
</script>
|
|
593
650
|
<script src="node_modules/ortoni-report/dist/utils/modal.js"></script>
|
|
594
651
|
</body>
|
|
595
|
-
|
|
596
652
|
</html>
|