ortoni-report 1.1.3 → 1.1.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/changelog.md +24 -0
- package/dist/css/main.css +22445 -0
- package/dist/ortoni-report.d.ts +6 -3
- package/dist/ortoni-report.js +16 -21
- package/dist/ortoni-report.mjs +16 -21
- package/dist/report-template.hbs +396 -319
- package/dist/utils/modal.js +12 -72
- package/package.json +1 -1
- package/readme.md +44 -15
- package/dist/css/pico.css +0 -2802
package/dist/report-template.hbs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
2
|
+
<html lang="en" data-theme="{{preferredTheme}}">
|
|
3
3
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8">
|
|
@@ -7,54 +7,39 @@
|
|
|
7
7
|
<meta name="description" content="Plawright HTML report by LetCode Koushik">
|
|
8
8
|
<title>Playwright Test Report</title>
|
|
9
9
|
<link rel="icon" href="node_modules/ortoni-report/dist/icon/32.png" type="image/x-icon">
|
|
10
|
-
<link rel="stylesheet" href="node_modules/ortoni-report/dist/css/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
main.container {
|
|
17
|
-
display: grid;
|
|
18
|
-
grid-template-columns: 1fr 2fr;
|
|
19
|
-
gap: 20px;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.header {
|
|
23
|
-
display: grid;
|
|
24
|
-
grid-template-columns: 1fr 2fr;
|
|
25
|
-
grid-column-gap: 20px;
|
|
26
|
-
grid-row-gap: 20px;
|
|
27
|
-
justify-items: stretch;
|
|
28
|
-
align-items: center;
|
|
29
|
-
justify-content: space-evenly;
|
|
10
|
+
<link rel="stylesheet" href="node_modules/ortoni-report/dist/css/main.css">
|
|
11
|
+
</head>
|
|
12
|
+
<style>
|
|
13
|
+
#summary, #testDetails, button#back-to-summary {
|
|
14
|
+
transition: opacity 0.2s ease-in-out;
|
|
30
15
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
color: var(--pico-primary-background);
|
|
16
|
+
.filter.active {
|
|
17
|
+
background-color: var(--bulma-background-active);
|
|
34
18
|
}
|
|
35
19
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
color:
|
|
20
|
+
::-webkit-scrollbar {
|
|
21
|
+
width: 0px;
|
|
22
|
+
background-color: transparent;
|
|
39
23
|
}
|
|
40
24
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
25
|
+
::-webkit-scrollbar-thumb {
|
|
26
|
+
background-color: var(--pico-secondary-background);
|
|
27
|
+
;
|
|
28
|
+
border-radius: 0px;
|
|
44
29
|
}
|
|
45
30
|
|
|
46
|
-
|
|
47
|
-
color:
|
|
31
|
+
::-webkit-scrollbar-thumb:hover {
|
|
32
|
+
background-color: var(--pico-secondary-background);
|
|
33
|
+
;
|
|
48
34
|
}
|
|
49
35
|
|
|
50
|
-
|
|
51
|
-
color: #
|
|
36
|
+
::-webkit-scrollbar-track {
|
|
37
|
+
background-color: #f1f1f1;
|
|
52
38
|
}
|
|
53
39
|
|
|
54
|
-
|
|
55
|
-
color: #
|
|
40
|
+
::-webkit-scrollbar-corner {
|
|
41
|
+
background-color: #fff;
|
|
56
42
|
}
|
|
57
|
-
|
|
58
43
|
div#testDetails {
|
|
59
44
|
position: sticky;
|
|
60
45
|
top: 0;
|
|
@@ -64,139 +49,149 @@
|
|
|
64
49
|
.sidebar {
|
|
65
50
|
overflow-y: auto;
|
|
66
51
|
max-height: calc(100vh - 100px);
|
|
67
|
-
/* Adjust as needed */
|
|
68
|
-
border-right: 1px solid #ddd;
|
|
69
|
-
padding-right: 10px;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
pre {
|
|
73
|
-
background-color: #f8f9fa;
|
|
74
|
-
padding: 1rem;
|
|
75
|
-
border-radius: 0.5rem;
|
|
76
|
-
overflow-x: auto;
|
|
77
52
|
}
|
|
78
53
|
|
|
79
|
-
|
|
80
|
-
display: none;
|
|
81
|
-
margin-bottom: 1rem;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.clickable {
|
|
54
|
+
aside li {
|
|
85
55
|
cursor: pointer;
|
|
86
|
-
transition: background-color 0.3s;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.clickable:hover {
|
|
90
|
-
background-color: #607D8B;
|
|
91
56
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
max-width: 25ch;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
li img {
|
|
101
|
-
max-width: 8%
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
summary img {
|
|
105
|
-
max-width: 5%
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
dialog article {
|
|
109
|
-
max-width: 768px;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
::-webkit-scrollbar {
|
|
113
|
-
width: 0px;
|
|
114
|
-
background-color: transparent;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
::-webkit-scrollbar-thumb {
|
|
118
|
-
background-color: var(--pico-secondary-background);
|
|
119
|
-
;
|
|
120
|
-
border-radius: 0px;
|
|
57
|
+
details summary {
|
|
58
|
+
cursor: pointer;
|
|
59
|
+
display: flex;
|
|
60
|
+
justify-content: space-between;
|
|
61
|
+
align-items: center;
|
|
121
62
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
background-
|
|
125
|
-
;
|
|
63
|
+
details summary::after {
|
|
64
|
+
content: '';
|
|
65
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
|
|
66
|
+
transform:rotate(-90deg);
|
|
67
|
+
background-size: 1em;
|
|
68
|
+
background-repeat: no-repeat;
|
|
69
|
+
background-position:right-center;
|
|
70
|
+
width: 1em;
|
|
71
|
+
height: 1em;
|
|
72
|
+
transition: transform 0.2s ease-in-out;
|
|
126
73
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
background-color: #f1f1f1;
|
|
74
|
+
details[open] > summary::after {
|
|
75
|
+
transform: rotate(0deg);
|
|
130
76
|
}
|
|
131
77
|
|
|
132
|
-
|
|
133
|
-
background-color: #fff;
|
|
134
|
-
}
|
|
135
|
-
</style>
|
|
136
|
-
</head>
|
|
78
|
+
</style>
|
|
137
79
|
|
|
138
80
|
<body>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
<div>
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
81
|
+
<!-- Header -->
|
|
82
|
+
<section class="section">
|
|
83
|
+
<header class="container">
|
|
84
|
+
<div class="columns is-vcentered">
|
|
85
|
+
<div class="column is-one-third">
|
|
86
|
+
{{!-- Custom Project Name --}}
|
|
87
|
+
{{#if projectName}}<h1 class="title">{{projectName}}</h1>{{/if}}
|
|
88
|
+
</div>
|
|
89
|
+
<div class="column">
|
|
90
|
+
<div class="control">
|
|
91
|
+
<input class="input" name="search" type="search" placeholder="Search by test title" />
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
<div class="column is-1">
|
|
95
|
+
<div class="control">
|
|
96
|
+
<button id="toggle-theme" data-theme-status="{{preferredTheme}}" class="button">Theme</button>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
147
99
|
</div>
|
|
148
|
-
</
|
|
149
|
-
</
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
<div>
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
100
|
+
</header>
|
|
101
|
+
</section>
|
|
102
|
+
|
|
103
|
+
<!-- Main Content -->
|
|
104
|
+
<section class="section">
|
|
105
|
+
<main class="container">
|
|
106
|
+
<div class="columns">
|
|
107
|
+
<aside class="column is-one-third sidebar">
|
|
108
|
+
<div class="columns">
|
|
109
|
+
<div class="column">
|
|
110
|
+
<h2 class="title is-4">Tests</h2>
|
|
111
|
+
</div>
|
|
112
|
+
<div class="column">
|
|
113
|
+
<div class="select is-pulled-right">
|
|
114
|
+
<select id="project-filter">
|
|
115
|
+
<option value="all">All Projects</option>
|
|
116
|
+
{{#each projects}}
|
|
117
|
+
<option value="{{this}}">{{this}}</option>
|
|
118
|
+
{{/each}}
|
|
119
|
+
</select>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
<div class="content">
|
|
124
|
+
{{#each groupedResults}}
|
|
125
|
+
<details class="box">
|
|
126
|
+
<summary class="is-size-5 has-icon-right">
|
|
127
|
+
<div class="icon-text">
|
|
128
|
+
<span class="icon has-text-info">
|
|
129
|
+
<img class="image is-16x16" src="node_modules/ortoni-report/dist/icon/file.png" alt="file name">
|
|
130
|
+
</span>
|
|
131
|
+
<span>{{@key}}</span>
|
|
132
|
+
</div>
|
|
167
133
|
</summary>
|
|
168
134
|
<ul>
|
|
169
135
|
{{#each this}}
|
|
170
136
|
<details>
|
|
171
|
-
<summary>
|
|
137
|
+
<summary class="is-size-5">
|
|
138
|
+
<div class="icon-text">
|
|
139
|
+
<span class="icon has-text-info">
|
|
140
|
+
<img class="image is-16x16" src="node_modules/ortoni-report/dist/icon/test.png" alt="test name">
|
|
141
|
+
</span>
|
|
142
|
+
<span>{{@key}}</span>
|
|
143
|
+
</div>
|
|
144
|
+
</summary>
|
|
172
145
|
<ul>
|
|
173
146
|
{{#each this}}
|
|
174
|
-
<
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
147
|
+
<details>
|
|
148
|
+
<summary>{{@key}}</summary>
|
|
149
|
+
<ul>
|
|
150
|
+
{{#each this}}
|
|
151
|
+
<li class="media" data-suite-name="{{suite}}"
|
|
152
|
+
data-project-name="{{projectName}}" data-test-id="{{index}}"
|
|
153
|
+
data-test-status="{{status}} {{retry}}">
|
|
154
|
+
<div class="icon-text">
|
|
155
|
+
{{#if isRetry}}
|
|
156
|
+
<span class="icon has-text-info">
|
|
157
|
+
<img class="image is-16x16" src="node_modules/ortoni-report/dist/icon/retry.png"
|
|
158
|
+
alt="Retry"></span>
|
|
159
|
+
{{/if}}
|
|
160
|
+
{{#if (eq status "passed")}}
|
|
161
|
+
<span class="icon has-text-info">
|
|
162
|
+
<img class="image is-16x16" src="node_modules/ortoni-report/dist/icon/pass.png"
|
|
163
|
+
alt="Pass"></span>
|
|
164
|
+
{{/if}}
|
|
165
|
+
{{#if (eq status "failed")}}
|
|
166
|
+
<span class="icon has-text-info">
|
|
167
|
+
<img class="image is-16x16" src="node_modules/ortoni-report/dist/icon/fail.png"
|
|
168
|
+
alt="Fail"></span>
|
|
169
|
+
{{else}}
|
|
170
|
+
{{#if (eq status "skipped")}}
|
|
171
|
+
<span class="icon has-text-info">
|
|
172
|
+
<img class="image is-16x16" src="node_modules/ortoni-report/dist/icon/skip.png"
|
|
173
|
+
alt="Skip"></span>
|
|
174
|
+
{{/if}}
|
|
175
|
+
{{/if}}
|
|
176
|
+
{{#if (eq status "timedOut")}}
|
|
177
|
+
<span class="icon has-text-info">
|
|
178
|
+
<img class="image is-16x16" src="node_modules/ortoni-report/dist/icon/timeout.png"
|
|
179
|
+
alt="timedOut"></span>
|
|
180
|
+
{{/if}}
|
|
181
|
+
{{#if (eq status "flaky")}}
|
|
182
|
+
<span class="icon has-text-info">
|
|
183
|
+
<img class="image is-16x16" src="node_modules/ortoni-report/dist/icon/flaky.png"
|
|
184
|
+
alt="flaky"></span>
|
|
185
|
+
{{/if}}
|
|
186
|
+
<span>{{title}}</span>
|
|
187
|
+
{{#if retryCount}}
|
|
188
|
+
<p>Retry Count: {{retryCount}}</p>
|
|
189
|
+
{{/if}}
|
|
190
|
+
</div>
|
|
191
|
+
</li>
|
|
192
|
+
{{/each}}
|
|
193
|
+
</ul>
|
|
194
|
+
</details>
|
|
200
195
|
{{/each}}
|
|
201
196
|
</ul>
|
|
202
197
|
</details>
|
|
@@ -204,81 +199,117 @@
|
|
|
204
199
|
</ul>
|
|
205
200
|
</details>
|
|
206
201
|
{{/each}}
|
|
207
|
-
</ul>
|
|
208
|
-
</details>
|
|
209
|
-
{{/each}}
|
|
210
|
-
</div>
|
|
211
|
-
</aside>
|
|
212
|
-
<section>
|
|
213
|
-
{{!-- Overall summary --}}
|
|
214
|
-
<div id="summary">
|
|
215
|
-
<section class="grid">
|
|
216
|
-
<div>
|
|
217
|
-
<article class="clickable filter" data-status="all">
|
|
218
|
-
<header>All Tests</header>
|
|
219
|
-
<p>{{totalCount}}</p>
|
|
220
|
-
</article>
|
|
221
|
-
</div>
|
|
222
|
-
<div>
|
|
223
|
-
<article class="clickable filter" data-status="passed">
|
|
224
|
-
<header>Passed</header>
|
|
225
|
-
<p class="text-success">{{passCount}}</p>
|
|
226
|
-
</article>
|
|
227
|
-
</div>
|
|
228
|
-
<div>
|
|
229
|
-
<article class="clickable filter" data-status="failed">
|
|
230
|
-
<header>Failed</header>
|
|
231
|
-
<p class="text-failure">{{failCount}}</p>
|
|
232
|
-
</article>
|
|
233
|
-
</div>
|
|
234
|
-
</section>
|
|
235
|
-
<section class="grid">
|
|
236
|
-
<div>
|
|
237
|
-
<article class="clickable filter" data-status="skipped">
|
|
238
|
-
<header>Skipped</header>
|
|
239
|
-
<p class="text-skip">{{skipCount}}</p>
|
|
240
|
-
</article>
|
|
241
202
|
</div>
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
<div>
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
203
|
+
</aside>
|
|
204
|
+
|
|
205
|
+
<section class="column">
|
|
206
|
+
{{!-- Overall summary --}}
|
|
207
|
+
<div id="summary">
|
|
208
|
+
<div class="columns is-multiline">
|
|
209
|
+
<div class="column is-one-third">
|
|
210
|
+
<div class="card is-clickable filter" data-status="all">
|
|
211
|
+
<header class="card-header has-text-centered">
|
|
212
|
+
<p class="card-header-title">All Tests</p>
|
|
213
|
+
</header>
|
|
214
|
+
<div class="card-content">
|
|
215
|
+
<div class="content">
|
|
216
|
+
<p class="has-text-centered has-text-primary">{{totalCount}}</p>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
<div class="column is-one-third">
|
|
222
|
+
<div class="card is-clickable filter" data-status="passed">
|
|
223
|
+
<header class="card-header has-text-centered">
|
|
224
|
+
<p class="card-header-title">Passed</p>
|
|
225
|
+
</header>
|
|
226
|
+
<div class="card-content">
|
|
227
|
+
<div class="content">
|
|
228
|
+
<p class="has-text-centered has-text-success">{{passCount}}</p>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
233
|
+
<div class="column is-one-third">
|
|
234
|
+
<div class="card is-clickable filter" data-status="failed">
|
|
235
|
+
<header class="card-header">
|
|
236
|
+
<p class="card-header-title has-text-centered">Failed</p>
|
|
237
|
+
</header>
|
|
238
|
+
<div class="card-content">
|
|
239
|
+
<div class="content">
|
|
240
|
+
<p class="has-text-centered has-text-danger">{{failCount}}</p>
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
<div class="columns is-multiline">
|
|
247
|
+
<div class="column is-one-third">
|
|
248
|
+
<div class="card is-clickable filter" data-status="skipped">
|
|
249
|
+
<header class="card-header has-text-centered">
|
|
250
|
+
<p class="card-header-title">Skipped</p>
|
|
251
|
+
</header>
|
|
252
|
+
<div class="card-content">
|
|
253
|
+
<div class="content">
|
|
254
|
+
<p class="has-text-centered has-text-info">{{skipCount}}</p>
|
|
255
|
+
</div>
|
|
256
|
+
</div>
|
|
257
|
+
</div>
|
|
266
258
|
</div>
|
|
267
|
-
<div class="
|
|
268
|
-
<
|
|
259
|
+
<div class="column is-one-third">
|
|
260
|
+
<div class="card is-clickable filter" data-status="flaky">
|
|
261
|
+
<header class="card-header has-text-centered">
|
|
262
|
+
<p class="card-header-title">Flaky</p>
|
|
263
|
+
</header>
|
|
264
|
+
<div class="card-content">
|
|
265
|
+
<div class="content">
|
|
266
|
+
<p class="has-text-centered has-text-warning">{{flakyCount}}</p>
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
<div class="column is-one-third">
|
|
272
|
+
<div class="card is-clickable filter" data-status="retry">
|
|
273
|
+
<header class="card-header has-text-centered">
|
|
274
|
+
<p class="card-header-title">Retry</p>
|
|
275
|
+
</header>
|
|
276
|
+
<div class="card-content">
|
|
277
|
+
<div class="content">
|
|
278
|
+
<p class="has-text-centered has-text-info">{{retryCount}}</p>
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
</div>
|
|
284
|
+
{{!-- Suite details with chart --}}
|
|
285
|
+
<div class="box">
|
|
286
|
+
<header class="has-text-centered title is-4">Suite</header>
|
|
287
|
+
<div class="columns">
|
|
288
|
+
<div class="column is-half">
|
|
289
|
+
{{#if authorName}}<h4>Author: {{authorName}}</h4>{{/if}}
|
|
290
|
+
{{#if testType}}<h4>Test Type: {{testType}}</h4>{{/if}}
|
|
291
|
+
{{#if totalDuration}}<h4>Duration: {{totalDuration}}</h4>{{/if}}
|
|
292
|
+
<h4>Success Rate: {{successRate}} %</h4>
|
|
293
|
+
<h4>Last Run: {{lastRunDate}}</h4>
|
|
294
|
+
</div>
|
|
295
|
+
<div class="column is-half">
|
|
296
|
+
<div class="chart-container">
|
|
297
|
+
<canvas id="testChart"></canvas>
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
269
300
|
</div>
|
|
270
301
|
</div>
|
|
271
|
-
</
|
|
302
|
+
</div>
|
|
303
|
+
{{!-- Test details --}}
|
|
304
|
+
<div id="testDetails" style="display: none;">
|
|
305
|
+
<!-- Back button should be outside the dynamic content -->
|
|
306
|
+
<button class="button content" id="back-to-summary"onclick="showSummary()">Back to Summary</button>
|
|
307
|
+
<!-- Test Details will be displayed here -->
|
|
308
|
+
</div>
|
|
272
309
|
</section>
|
|
273
310
|
</div>
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
<!-- Back button should be outside the dynamic content -->
|
|
277
|
-
<button class="back-button" onclick="showSummary()">Back to Summary</button>
|
|
278
|
-
<!-- Test Details will be displayed here -->
|
|
279
|
-
</div>
|
|
280
|
-
</section>
|
|
281
|
-
</main>
|
|
311
|
+
</main>
|
|
312
|
+
</section>
|
|
282
313
|
<script src="node_modules/ortoni-report/dist/utils/chart.js"></script>
|
|
283
314
|
<script>
|
|
284
315
|
function escapeHtml(unsafe) {
|
|
@@ -294,88 +325,132 @@
|
|
|
294
325
|
});
|
|
295
326
|
}
|
|
296
327
|
|
|
297
|
-
|
|
298
|
-
|
|
328
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
329
|
+
const testData = {{{ json results }}};
|
|
299
330
|
const testDetails = document.getElementById('testDetails');
|
|
300
331
|
const summary = document.getElementById('summary');
|
|
301
|
-
const backButton = document.querySelector('
|
|
302
|
-
|
|
332
|
+
const backButton = document.querySelector('button#back-to-summary');
|
|
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
|
+
}
|
|
347
|
+
|
|
348
|
+
themeButton.addEventListener('click', () => {
|
|
349
|
+
const currentTheme = htmlElement.getAttribute('data-theme');
|
|
350
|
+
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
|
|
351
|
+
htmlElement.setAttribute('data-theme', newTheme);
|
|
352
|
+
if (newTheme === 'dark') {
|
|
353
|
+
themeButton.classList.remove('is-light');
|
|
354
|
+
themeButton.classList.add('is-dark');
|
|
355
|
+
themeButton.textContent = 'Dark';
|
|
356
|
+
} else {
|
|
357
|
+
themeButton.classList.remove('is-dark');
|
|
358
|
+
themeButton.classList.add('is-light');
|
|
359
|
+
themeButton.textContent = 'Light';
|
|
360
|
+
}
|
|
361
|
+
});
|
|
303
362
|
|
|
304
363
|
function showSummary() {
|
|
305
364
|
summary.style.display = 'block';
|
|
306
365
|
testDetails.style.display = 'none';
|
|
307
366
|
backButton.style.display = 'none';
|
|
308
|
-
if (highlightedItem) {
|
|
309
|
-
highlightedItem.classList.remove('highlight');
|
|
310
|
-
}
|
|
311
367
|
}
|
|
312
368
|
|
|
313
369
|
window.showSummary = showSummary;
|
|
314
370
|
|
|
315
371
|
function displayTestDetails(test) {
|
|
316
|
-
summary
|
|
317
|
-
testDetails
|
|
318
|
-
backButton
|
|
372
|
+
const summary = document.getElementById('summary');
|
|
373
|
+
const testDetails = document.getElementById('testDetails');
|
|
374
|
+
const backButton = document.querySelector('button#back-to-summary');
|
|
375
|
+
summary.style.display = 'none';
|
|
376
|
+
testDetails.style.opacity = '0';
|
|
377
|
+
testDetails.style.display = 'block';
|
|
378
|
+
setTimeout(() => {
|
|
379
|
+
testDetails.style.opacity = '1';
|
|
380
|
+
backButton.style.opacity = '1';
|
|
381
|
+
}, 50);
|
|
382
|
+
|
|
383
|
+
|
|
319
384
|
let statusClass = '';
|
|
320
385
|
let statusText = test.status.toUpperCase();
|
|
321
386
|
if (test.status.startsWith('passed')) {
|
|
322
|
-
statusClass = '
|
|
387
|
+
statusClass = 'tag is-success';
|
|
323
388
|
} else if (test.status === 'flaky') {
|
|
324
|
-
statusClass = '
|
|
389
|
+
statusClass = 'tag is-warning';
|
|
390
|
+
} else if (test.status === 'failed') {
|
|
391
|
+
statusClass = 'tag is-danger';
|
|
325
392
|
} else {
|
|
326
|
-
statusClass = '
|
|
327
|
-
}
|
|
393
|
+
statusClass = 'tag is-info';
|
|
394
|
+
}
|
|
395
|
+
|
|
328
396
|
testDetails.innerHTML = `
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
<
|
|
343
|
-
<
|
|
344
|
-
<
|
|
345
|
-
<
|
|
346
|
-
<p>
|
|
347
|
-
<strong>Screenshot</strong>
|
|
397
|
+
<button class="button content" id="back-to-summary" style="display: block" onclick="showSummary()">Back to Summary</button>
|
|
398
|
+
<h3 class="title is-3 has-text-centered">${test.title}</h3>
|
|
399
|
+
<div class="columns">
|
|
400
|
+
<div class="column content">
|
|
401
|
+
<h4 class="title is-4">Status</h4>
|
|
402
|
+
<p class="${statusClass}">${statusText}</p>
|
|
403
|
+
${test.duration.length > 0 ? `
|
|
404
|
+
<h4 class="title is-4">Duration</h4>
|
|
405
|
+
<p class="${statusClass}">${test.duration}</p>` : ""}
|
|
406
|
+
</div>
|
|
407
|
+
<div class="column content">
|
|
408
|
+
${test.screenshotPath ? `
|
|
409
|
+
<div id="modal-js-example" class="modal">
|
|
410
|
+
<div class="modal-background"></div>
|
|
411
|
+
<div class="modal-content">
|
|
412
|
+
<p class="image is-16by9">
|
|
413
|
+
<img src="data:image/png;base64, ${test.screenshotPath}" alt="Screenshot">
|
|
348
414
|
</p>
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
</article>
|
|
352
|
-
</dialog>` : ''}
|
|
415
|
+
</div>
|
|
416
|
+
<button onclick="closeModal()" class="modal-close is-large" aria-label="close"></button>
|
|
353
417
|
</div>
|
|
418
|
+
<figure class="image is-16by9">
|
|
419
|
+
<img onclick="openModal()" src="data:image/png;base64, ${test.screenshotPath}" alt="Screenshot">
|
|
420
|
+
</figure>` : ''}
|
|
354
421
|
</div>
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
</
|
|
360
|
-
|
|
361
|
-
|
|
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>
|
|
362
432
|
${test.errors.length ? `
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
433
|
+
<h4 class="title is-4">Errors</h4>
|
|
434
|
+
<div class="content">
|
|
435
|
+
<pre>${escapeHtml(test.errors.join('\n'))}</pre>
|
|
436
|
+
</div>` : ''}
|
|
437
|
+
</div>
|
|
438
|
+
<div>
|
|
369
439
|
${test.logs ? `
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
440
|
+
<h4 class="title is-4">Logs</h4>
|
|
441
|
+
<div class="box">
|
|
442
|
+
<pre>${escapeHtml(test.logs)}</pre>
|
|
443
|
+
</div>` : ''}
|
|
444
|
+
</div>
|
|
445
|
+
`;
|
|
446
|
+
|
|
376
447
|
const stepDetailsDiv = document.getElementById('stepDetails');
|
|
377
|
-
|
|
378
|
-
|
|
448
|
+
if(stepDetailsDiv){
|
|
449
|
+
const stepsList = attachSteps(test);
|
|
450
|
+
const detail = document.getElementById("stepopen");
|
|
451
|
+
detail.setAttribute("open", "");
|
|
452
|
+
stepDetailsDiv.appendChild(stepsList);
|
|
453
|
+
}
|
|
379
454
|
}
|
|
380
455
|
|
|
381
456
|
function attachSteps(test) {
|
|
@@ -384,7 +459,7 @@
|
|
|
384
459
|
stepsList.innerHTML = '';
|
|
385
460
|
test.steps.forEach(step => {
|
|
386
461
|
const li = document.createElement('li');
|
|
387
|
-
li.innerHTML = `<strong class
|
|
462
|
+
li.innerHTML = `<strong class="${step.error ? 'has-text-danger' : ''}">${step.title}</strong>`;
|
|
388
463
|
stepsList.appendChild(li);
|
|
389
464
|
});
|
|
390
465
|
return stepsList;
|
|
@@ -397,11 +472,6 @@
|
|
|
397
472
|
const testId = item.getAttribute('data-test-id');
|
|
398
473
|
const test = testData[testId];
|
|
399
474
|
displayTestDetails(test);
|
|
400
|
-
if (highlightedItem) {
|
|
401
|
-
highlightedItem.classList.remove('highlight');
|
|
402
|
-
}
|
|
403
|
-
item.classList.add('highlight');
|
|
404
|
-
highlightedItem = item;
|
|
405
475
|
});
|
|
406
476
|
});
|
|
407
477
|
|
|
@@ -411,19 +481,26 @@
|
|
|
411
481
|
filter.addEventListener('click', () => {
|
|
412
482
|
const status = filter.getAttribute('data-status');
|
|
413
483
|
filters.forEach(f => {
|
|
414
|
-
if (f.getAttribute('data-status')
|
|
484
|
+
if (f.getAttribute('data-status')) {
|
|
415
485
|
f.classList.remove('active');
|
|
416
486
|
}
|
|
417
487
|
});
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
}
|
|
421
|
-
applyFilter(status);
|
|
488
|
+
filter.classList.add('active');
|
|
489
|
+
applyFilters();
|
|
422
490
|
});
|
|
423
491
|
});
|
|
492
|
+
|
|
493
|
+
const projectFilter = document.getElementById('project-filter');
|
|
494
|
+
projectFilter.addEventListener('change', () => {
|
|
495
|
+
applyFilters();
|
|
496
|
+
});
|
|
424
497
|
}
|
|
425
498
|
|
|
426
|
-
function
|
|
499
|
+
function applyFilters() {
|
|
500
|
+
const selectedProject = document.getElementById('project-filter').value;
|
|
501
|
+
const activeFilter = document.querySelector('.filter.active');
|
|
502
|
+
const selectedStatus = activeFilter ? activeFilter.getAttribute('data-status') : 'all';
|
|
503
|
+
|
|
427
504
|
const testItems = document.querySelectorAll('li[data-test-id]');
|
|
428
505
|
const detailsElements = document.querySelectorAll('details');
|
|
429
506
|
|
|
@@ -431,30 +508,28 @@
|
|
|
431
508
|
let shouldShowDetails = false;
|
|
432
509
|
const items = details.querySelectorAll('li[data-test-id]');
|
|
433
510
|
items.forEach(item => {
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
item.
|
|
444
|
-
shouldShowDetails = true;
|
|
511
|
+
const projectName = item.getAttribute('data-project-name').trim();
|
|
512
|
+
const testStatus = item.getAttribute('data-test-status').trim();
|
|
513
|
+
const matchesProject = (selectedProject === 'all' || projectName === selectedProject);
|
|
514
|
+
const matchesStatus = (selectedStatus === 'all' || testStatus.includes(selectedStatus) ||
|
|
515
|
+
(selectedStatus === 'failed' && (testStatus === 'failed' || testStatus === 'timedOut')) ||
|
|
516
|
+
(selectedStatus === 'retry' && testStatus.includes('retry')) ||
|
|
517
|
+
(selectedStatus === 'flaky' && testStatus.includes('flaky')));
|
|
518
|
+
|
|
519
|
+
if (matchesProject && matchesStatus) {
|
|
520
|
+
item.classList.remove('is-hidden');
|
|
521
|
+
shouldShowDetails = true;
|
|
445
522
|
} else {
|
|
446
|
-
item.
|
|
523
|
+
item.classList.add('is-hidden');
|
|
447
524
|
}
|
|
448
525
|
});
|
|
449
|
-
details.open = shouldShowDetails;
|
|
450
|
-
details.
|
|
526
|
+
details.open = shouldShowDetails;
|
|
527
|
+
details.classList.toggle('is-hidden', !shouldShowDetails);
|
|
451
528
|
});
|
|
452
529
|
}
|
|
453
530
|
|
|
454
|
-
|
|
455
531
|
const searchInput = document.querySelector('input[name="search"]');
|
|
456
532
|
const detailsElements = document.querySelectorAll('details');
|
|
457
|
-
|
|
458
533
|
searchInput.addEventListener('input', () => {
|
|
459
534
|
const searchTerm = searchInput.value.toLowerCase();
|
|
460
535
|
const testItems = document.querySelectorAll('[data-test-id]');
|
|
@@ -497,23 +572,25 @@
|
|
|
497
572
|
labels: ['Passed', 'Failed', 'Skipped','Flaky'],
|
|
498
573
|
datasets: [{
|
|
499
574
|
data: [{{ passCount }}, {{ failCount }}, {{ skipCount }}, {{flakyCount}}],
|
|
500
|
-
|
|
575
|
+
backgroundColor: ['#28a745', '#dc3545', '#d5d4a1', '#FFB704']
|
|
501
576
|
}]
|
|
502
577
|
},
|
|
503
578
|
options: {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
579
|
+
responsive: true,
|
|
580
|
+
maintainAspectRatio: false,
|
|
581
|
+
plugins: {
|
|
582
|
+
legend: {
|
|
583
|
+
position: 'bottom'
|
|
584
|
+
}
|
|
509
585
|
}
|
|
510
586
|
}
|
|
511
|
-
}
|
|
512
|
-
});
|
|
513
|
-
attachEventListeners();
|
|
514
587
|
});
|
|
515
|
-
|
|
516
|
-
|
|
588
|
+
|
|
589
|
+
attachEventListeners();
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
</script>
|
|
593
|
+
<script src="node_modules/ortoni-report/dist/utils/modal.js"></script>
|
|
517
594
|
</body>
|
|
518
595
|
|
|
519
596
|
</html>
|