@magnit-ce/code-tests 0.0.13 → 0.0.14
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/README.md +95 -64
- package/dist/code-tests.d.ts +172 -58
- package/dist/code-tests.js +1178 -1012
- package/dist/code-tests.min.js +1 -475
- package/dist/code-tests.umd.js +1434 -0
- package/dist/code-tests.umd.min.js +1 -0
- package/package.json +25 -24
- package/dist/code-tests.cjs +0 -1296
- package/dist/code-tests.d.cts +0 -58
package/dist/code-tests.js
CHANGED
|
@@ -1,217 +1,137 @@
|
|
|
1
|
-
|
|
2
|
-
var code_tests_default = `:host
|
|
1
|
+
const style = `:host
|
|
3
2
|
{
|
|
4
|
-
|
|
5
|
-
--
|
|
6
|
-
--
|
|
3
|
+
--gap: 7px;
|
|
4
|
+
--gap-small: 3px;
|
|
5
|
+
--gap-medium: 14px;
|
|
6
|
+
--gap-large: 24px;
|
|
7
|
+
|
|
8
|
+
--surface-success: oklch(93.96% 0.05 148.74);
|
|
9
|
+
--primary-success: oklch(58.83% 0.158 145.05);
|
|
10
|
+
--border-success: solid 1px var(--primary-success);
|
|
7
11
|
|
|
8
|
-
--
|
|
9
|
-
--
|
|
12
|
+
--surface-fail: oklch(88.98% 0.052 3.28);
|
|
13
|
+
--primary-fail: oklch(45.8% 0.177 17.7);
|
|
14
|
+
--border-fail: solid 1px var(--primary-fail);
|
|
10
15
|
|
|
11
|
-
--
|
|
12
|
-
--
|
|
16
|
+
--surface-process: oklch(89.66% 0.046 260.67);
|
|
17
|
+
--primary-process: oklch(43.48% 0.17 260.2);
|
|
18
|
+
--border-process: solid 1px var(--primary-process);
|
|
13
19
|
|
|
14
|
-
/*** red ***/
|
|
15
|
-
--uchu-light-red-raw: 88.98% 0.052 3.28;
|
|
16
|
-
--uchu-light-red: oklch(var(--uchu-light-red-raw));
|
|
17
20
|
|
|
18
|
-
--uchu-dark-red-raw: 45.8% 0.177 17.7;
|
|
19
|
-
--uchu-dark-red: oklch(var(--uchu-dark-red-raw));
|
|
20
21
|
|
|
21
|
-
/*** purple ***/
|
|
22
|
-
--uchu-light-purple-raw: 89.1% 0.046 305.24;
|
|
23
|
-
--uchu-light-purple: oklch(var(--uchu-light-purple-raw));
|
|
24
|
-
|
|
25
|
-
--uchu-dark-purple-raw: 39.46% 0.164 298.29;
|
|
26
|
-
--uchu-dark-purple: oklch(var(--uchu-dark-purple-raw));
|
|
27
|
-
|
|
28
|
-
/*** blue ***/
|
|
29
|
-
--uchu-light-blue-raw: 89.66% 0.046 260.67;
|
|
30
|
-
--uchu-light-blue: oklch(var(--uchu-light-blue-raw));
|
|
31
|
-
|
|
32
|
-
--uchu-blue-raw: 62.39% 0.181 258.33;
|
|
33
|
-
--uchu-blue: oklch(var(--uchu-blue-raw));
|
|
34
|
-
|
|
35
|
-
--uchu-dark-blue-raw: 43.48% 0.17 260.2;
|
|
36
|
-
--uchu-dark-blue: oklch(var(--uchu-dark-blue-raw));
|
|
37
|
-
|
|
38
|
-
/*** green ***/
|
|
39
|
-
--uchu-light-green-raw: 93.96% 0.05 148.74;
|
|
40
|
-
--uchu-light-green: oklch(var(--uchu-light-green-raw));
|
|
41
|
-
|
|
42
|
-
--uchu-green-raw: 79.33% 0.179 145.62;
|
|
43
|
-
--uchu-green: oklch(var(--uchu-green-raw));
|
|
44
|
-
|
|
45
|
-
--uchu-dark-green-raw: 58.83% 0.158 145.05;
|
|
46
|
-
--uchu-dark-green: oklch(var(--uchu-dark-green-raw));
|
|
47
|
-
|
|
48
|
-
/*** general ***/
|
|
49
|
-
--uchu-yang-raw: 99.4% 0 0;
|
|
50
|
-
--uchu-yang: oklch(var(--uchu-yang-raw));
|
|
51
|
-
|
|
52
|
-
--uchu-yin-raw: 14.38% 0.007 256.88;
|
|
53
|
-
--uchu-yin: oklch(var(--uchu-yin-raw));
|
|
54
|
-
|
|
55
|
-
/*** code-tests vars ***/
|
|
56
|
-
|
|
57
|
-
--spacer: calc(1em - 7px);
|
|
58
|
-
--small-spacer: calc(var(--spacer) / 2);
|
|
59
|
-
|
|
60
|
-
--color-success: var(--uchu-green);
|
|
61
|
-
--color-fail: var(--uchu-red);
|
|
62
|
-
--color-process: var(--uchu-blue);
|
|
63
|
-
|
|
64
|
-
--text-surface: var(--uchu-yin);
|
|
65
|
-
--text-result: var(--uchu-yang); /* --uchu-yang: #fdfdfd; */
|
|
66
|
-
--text-collapse-icon: var(--uchu-dark-gray); /* --uchu-dark-gray: #878a8b; */
|
|
67
|
-
--text-hook-summary: var(--uchu-dark-purple);
|
|
68
|
-
--text-success: var(--uchu-dark-green); /* --uchu-dark-green: #2e943a; */
|
|
69
|
-
--text-fail: var(--uchu-dark-red); /* --uchu-dark-red: #a30d30; */
|
|
70
|
-
--text-process: var(--uchu-dark-blue); /* --uchu-dark-blue: #0949ac; */
|
|
71
|
-
--text-button: var(--uchu-yang); /* --uchu-dark-blue: #0949ac; */
|
|
72
|
-
--text-placeholder: var(--uchu-dark-gray);
|
|
73
|
-
|
|
74
|
-
--surface-0: var(--uchu-light-gray);
|
|
75
|
-
--surface-test: var(--uchu-yang);
|
|
76
22
|
--surface-test-summary: var(--uchu-gray);
|
|
77
23
|
--surface-hook-summary: var(--uchu-light-purple);
|
|
78
|
-
--surface-
|
|
79
|
-
|
|
80
|
-
--surface-process: var(--uchu-light-blue);
|
|
81
|
-
--surface-button: var(--uchu-blue); /* --uchu-blue: #3984f2 */
|
|
82
|
-
--surface-button-hover: var(--uchu-light-blue);
|
|
83
|
-
--surface-button-active: var(--uchu-dark-blue);
|
|
84
|
-
--surface-button-cancel: var(--uchu-dark-blue);
|
|
85
|
-
|
|
24
|
+
--surface-hook-any-summary: var(--uchu-light-blue);
|
|
25
|
+
|
|
86
26
|
--border-test: solid 1px var(--uchu-dark-gray);
|
|
87
27
|
--border-hook: solid 1px var(--uchu-dark-purple);
|
|
88
|
-
--border-
|
|
89
|
-
--border-fail: solid 1px var(--uchu-dark-red);
|
|
90
|
-
--border-process: solid 1px var(--uchu-dark-blue);
|
|
28
|
+
--border-hook-any: solid 1px var(--uchu-dark-blue);
|
|
91
29
|
--border-button: solid 1px var(--uchu-blue);
|
|
92
|
-
|
|
30
|
+
|
|
93
31
|
--success-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="%232e943a" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg>');
|
|
94
32
|
--info-icon: url('data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2022.812714%2022.814663%22%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Asvg%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20style%3D%22fill%3Atransparent%3Bstroke%3Atransparent%3Bstroke-width%3A0.999999%3Bstroke-linejoin%3Around%3Bstroke-miterlimit%3A6.3%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A29.2913%3Bstroke-opacity%3A1%22%20d%3D%22M%2022.295505%2C11.407332%20A%2010.889144%2C10.889144%200%200%201%2011.406424%2C22.296479%2010.889144%2C10.889144%200%200%201%200.51720881%2C11.407332%2010.889144%2C10.889144%200%200%201%2011.406424%2C0.51818382%2010.889144%2C10.889144%200%200%201%2022.295505%2C11.407332%20Z%22%3E%3C%2Fpath%3E%3Cpath%20d%3D%22m%2013.945668%2C4.3053761%20c%200.150778%2C-0.96462%20-0.30687%2C-1.43709%20-1.36997%2C-1.43709%20-1.063%2C0%20-1.668452%2C0.47247%20-1.81923%2C1.43709%20-0.150779%2C0.96462%200.306971%2C1.43708%201.369971%2C1.43708%201.004%2C0%201.66845%2C-0.47246%201.819229%2C-1.43708%20z%20M%2011.693889%2C17.829726%2013.373994%2C7.0811161%20h%20-2.9333%20L%208.7605887%2C17.829726%20Z%22%20style%3D%22font-size%3A19.6861px%3Bfont-family%3APassageway%3B-inkscape-font-specification%3APassageway%3Bfill%3A%23a30d30%3Bstroke-width%3A2.5%3Bstroke-linejoin%3Around%3Bstroke-miterlimit%3A6.3%3Bstroke-dashoffset%3A29.2913%22%20aria-label%3D%22i%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E');
|
|
95
33
|
|
|
96
|
-
--font-text: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
|
97
|
-
|
|
98
|
-
/*** styles ***/
|
|
99
34
|
|
|
100
|
-
color-scheme: light dark;
|
|
101
35
|
display: grid;
|
|
102
|
-
gap: var(--
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
font-family: var(--font-text);
|
|
36
|
+
gap: var(--gap);
|
|
37
|
+
grid-auto-rows: max-content;
|
|
38
|
+
font-family: sans-serif;
|
|
39
|
+
font-size: 12px;
|
|
107
40
|
}
|
|
108
41
|
|
|
109
42
|
#header
|
|
110
43
|
{
|
|
111
|
-
|
|
112
|
-
|
|
44
|
+
flex: 1;
|
|
45
|
+
display: flex;
|
|
113
46
|
align-items: center;
|
|
114
|
-
gap: var(--
|
|
115
|
-
|
|
116
|
-
padding: var(--spacer);
|
|
117
|
-
margin-bottom: var(--spacer);
|
|
118
|
-
user-select: none;
|
|
47
|
+
gap: var(--gap);
|
|
48
|
+
padding: var(--gap-small) var(--gap);
|
|
119
49
|
}
|
|
120
|
-
|
|
121
50
|
#title
|
|
122
51
|
{
|
|
123
|
-
|
|
124
|
-
font-size: 16px;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
.hook
|
|
128
|
-
{
|
|
129
|
-
display: none;
|
|
130
|
-
}
|
|
131
|
-
:host(.has-before-hook) #before-all-details
|
|
132
|
-
,:host(.has-after-hook) #after-all-details
|
|
133
|
-
{
|
|
134
|
-
display: initial;
|
|
135
|
-
}
|
|
136
|
-
:host(.has-required-before-hook) #required-before-any-details
|
|
137
|
-
,:host(.has-required-after-hook) #required-after-any-details
|
|
138
|
-
{
|
|
139
|
-
display: initial;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
#required-before-any-summary
|
|
143
|
-
,#required-after-any-summary
|
|
144
|
-
{
|
|
145
|
-
background: var(--surface-process);
|
|
146
|
-
color: var(--text-process);
|
|
147
|
-
border: solid 1px var(--text-process);
|
|
148
|
-
grid-template-columns: auto auto 1fr;
|
|
52
|
+
flex: 1;
|
|
149
53
|
}
|
|
150
54
|
|
|
151
55
|
#tests
|
|
56
|
+
,#component-content
|
|
152
57
|
{
|
|
153
|
-
margin: 0;
|
|
154
|
-
padding: 0;
|
|
155
|
-
list-style: none;
|
|
156
58
|
display: grid;
|
|
59
|
+
gap: var(--gap);
|
|
157
60
|
grid-auto-rows: max-content;
|
|
158
|
-
gap: var(--spacer);
|
|
159
61
|
}
|
|
160
62
|
|
|
161
|
-
|
|
63
|
+
#header button
|
|
162
64
|
{
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
padding: var(--small-spacer) var(--spacer);
|
|
65
|
+
align-self: stretch;
|
|
66
|
+
display: inline-flex;
|
|
166
67
|
align-items: center;
|
|
68
|
+
gap: var(--gap-small);
|
|
167
69
|
}
|
|
168
|
-
|
|
70
|
+
|
|
71
|
+
button .reset-icon
|
|
169
72
|
{
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
73
|
+
width: 1em;
|
|
74
|
+
height: 1em;
|
|
75
|
+
transform: scaleX(-1);
|
|
76
|
+
margin-inline: 3px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Run button */
|
|
80
|
+
button .arrow-icon
|
|
81
|
+
{
|
|
82
|
+
width: .75em;
|
|
83
|
+
height: .75em;
|
|
174
84
|
transform: rotate(-90deg);
|
|
175
|
-
|
|
85
|
+
margin-inline: 3px;
|
|
176
86
|
}
|
|
177
|
-
|
|
87
|
+
:host(.running) .run-all-button-icon
|
|
88
|
+
,:host(.fail) .run-all-button-icon
|
|
178
89
|
{
|
|
179
90
|
transform: rotate(0);
|
|
180
|
-
/* background: var(--surface-test-summary); */
|
|
181
91
|
}
|
|
182
92
|
|
|
183
|
-
|
|
93
|
+
/* Dropdown Layout */
|
|
94
|
+
summary > .run-test-button
|
|
95
|
+
, #run-all-button
|
|
184
96
|
{
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
border-color: oklch(63.12% 0.004 219.55);
|
|
97
|
+
justify-self: flex-end;
|
|
98
|
+
margin-left: auto;
|
|
188
99
|
}
|
|
189
|
-
|
|
100
|
+
|
|
101
|
+
summary:not(#component-summary)
|
|
190
102
|
{
|
|
191
|
-
|
|
192
|
-
border-color: oklch(63.12% 0.004 219.55);
|
|
103
|
+
padding: var(--gap-small) var(--gap);
|
|
193
104
|
}
|
|
194
|
-
|
|
105
|
+
#component-summary
|
|
195
106
|
{
|
|
196
|
-
|
|
197
|
-
border-color: oklch(53.12% 0.004 219.55);
|
|
107
|
+
padding-block: var(--gap-small);
|
|
198
108
|
}
|
|
199
|
-
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
/* Dropdown Markers */
|
|
112
|
+
summary
|
|
200
113
|
{
|
|
201
|
-
display:
|
|
114
|
+
display: flex;
|
|
115
|
+
align-items: center;
|
|
116
|
+
gap: var(--gap);
|
|
202
117
|
}
|
|
203
|
-
|
|
204
|
-
#before-all-summary
|
|
205
|
-
,#after-all-summary
|
|
118
|
+
summary > .arrow-icon
|
|
206
119
|
{
|
|
207
|
-
background: var(--
|
|
208
|
-
|
|
209
|
-
|
|
120
|
+
background: var(--arrow-icon);
|
|
121
|
+
transform: rotate(-90deg);
|
|
122
|
+
transition: transform ease-out 90ms;
|
|
123
|
+
width: .6em;
|
|
124
|
+
height: .6em;
|
|
125
|
+
}
|
|
126
|
+
details[open] > summary > .arrow-icon
|
|
127
|
+
{
|
|
128
|
+
transform: rotate(0);
|
|
210
129
|
}
|
|
211
130
|
|
|
131
|
+
/* Result Icon */
|
|
212
132
|
.result-icon
|
|
213
133
|
{
|
|
214
|
-
--background-size:
|
|
134
|
+
--background-size: 16px;
|
|
215
135
|
width: var(--background-size);
|
|
216
136
|
height: var(--background-size);
|
|
217
137
|
|
|
@@ -224,184 +144,196 @@ summary::before
|
|
|
224
144
|
}
|
|
225
145
|
.result-icon::before
|
|
226
146
|
{
|
|
227
|
-
content: '
|
|
147
|
+
content: '⋯';
|
|
148
|
+
font-size: 10px;
|
|
228
149
|
}
|
|
229
150
|
|
|
230
|
-
.
|
|
231
|
-
|
|
232
|
-
border: var(--border-hook);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
.test
|
|
236
|
-
,#before-all-details
|
|
237
|
-
,#after-all-details
|
|
238
|
-
{
|
|
239
|
-
border: var(--border-test);
|
|
240
|
-
border-radius: 2px;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
.test summary
|
|
244
|
-
{
|
|
245
|
-
background: var(--surface-test-summary);
|
|
246
|
-
grid-template-columns: auto auto 1fr auto;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
.test.running .result-icon
|
|
151
|
+
:host(.running) #component-summary .result-icon
|
|
152
|
+
,.test.running .test-summary > .result-icon
|
|
250
153
|
,.hook.running .result-icon
|
|
154
|
+
,.processing-details.running .processing-result-icon
|
|
251
155
|
{
|
|
252
156
|
border: var(--border-process);
|
|
253
157
|
background: var(--surface-process);
|
|
254
158
|
}
|
|
255
|
-
.
|
|
159
|
+
:host(.success) #component-summary .result-icon
|
|
160
|
+
,.test.success .test-summary > .result-icon
|
|
256
161
|
,.hook.success .result-icon
|
|
162
|
+
,.processing-details.success .processing-result-icon
|
|
257
163
|
{
|
|
258
164
|
border: var(--border-success);
|
|
259
165
|
background: var(--surface-success)
|
|
260
166
|
var(--success-icon);
|
|
261
167
|
background-repeat: no-repeat;
|
|
262
168
|
background-position: center;
|
|
263
|
-
background-size: var(--icon-size,
|
|
169
|
+
background-size: var(--icon-size, 12px) var(--icon-size, 12px);
|
|
264
170
|
}
|
|
265
|
-
.
|
|
171
|
+
:host(.fail) #component-summary .result-icon
|
|
172
|
+
,.test.fail .test-summary > .result-icon
|
|
266
173
|
,.hook.fail .result-icon
|
|
174
|
+
,.processing-details.fail .processing-result-icon
|
|
267
175
|
{
|
|
268
176
|
border: var(--border-fail);
|
|
269
177
|
background: var(--surface-fail)
|
|
270
178
|
var(--info-icon);
|
|
179
|
+
background-size: var(--icon-size, 16px) var(--icon-size, 16px);
|
|
271
180
|
background-repeat: no-repeat;
|
|
272
181
|
background-position: center;
|
|
273
182
|
transform: rotate(175deg);
|
|
274
183
|
}
|
|
275
|
-
|
|
184
|
+
:host(:is(.success,.fail)) #component-summary .result-icon::before
|
|
185
|
+
,.test:is(.success,.fail) .test-summary > .result-icon::before
|
|
276
186
|
,.hook:is(.success,.fail) .result-icon::before
|
|
187
|
+
,.processing-details:is(.success,.fail) .processing-result-icon::before
|
|
277
188
|
{
|
|
278
189
|
display: none;
|
|
279
190
|
}
|
|
280
|
-
|
|
191
|
+
:host(.running) #component-summary .result-icon::before
|
|
192
|
+
,.test:is(.running) .test-summary > .result-icon::before
|
|
281
193
|
,.hook:is(.running) .result-icon::before
|
|
194
|
+
,.processing-details:is(.running) .processing-result-icon::before
|
|
282
195
|
{
|
|
283
196
|
content: '';
|
|
284
|
-
--color: var(--
|
|
197
|
+
--color: var(--primary-process, currentColor);
|
|
285
198
|
--animation-timing-function: linear;
|
|
286
199
|
--animation-duration: 2s;
|
|
287
|
-
width: var(--icon-size,
|
|
288
|
-
height: var(--icon-size,
|
|
289
|
-
mask-image: radial-gradient(circle at 50% 50%, transparent calc(var(--icon-size,
|
|
200
|
+
width: var(--icon-size, 14px);
|
|
201
|
+
height: var(--icon-size, 14px);
|
|
202
|
+
mask-image: radial-gradient(circle at 50% 50%, transparent calc(var(--icon-size, 14px) / 3), black calc(var(--icon-size, 14px) / 3));
|
|
290
203
|
background-image: conic-gradient(transparent, transparent 135deg, var(--color));
|
|
291
204
|
border-radius: 50%;
|
|
292
205
|
animation: var(--animation-timing-function) var(--animation-duration) infinite spin;
|
|
293
206
|
margin: 2px;
|
|
294
207
|
}
|
|
295
208
|
|
|
296
|
-
|
|
209
|
+
/* Smaller Result icon settings for sub-test icons */
|
|
210
|
+
.before-each-result-icon
|
|
211
|
+
,.after-each-result-icon
|
|
212
|
+
,.processing-result-icon
|
|
297
213
|
{
|
|
298
|
-
|
|
214
|
+
--background-size: 12px;
|
|
299
215
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
,.
|
|
216
|
+
.before-each-result-icon::before
|
|
217
|
+
,.after-each-result-icon::before
|
|
218
|
+
,.processing-result-icon::before
|
|
303
219
|
{
|
|
304
|
-
|
|
305
|
-
border: var(--border-test);
|
|
306
|
-
border-radius: 2px;
|
|
307
|
-
margin: var(--small-spacer);
|
|
220
|
+
font-size: 9px;
|
|
308
221
|
}
|
|
309
|
-
|
|
310
|
-
.
|
|
311
|
-
,.
|
|
222
|
+
.hook.success .before-each-result-icon
|
|
223
|
+
,.hook.success .after-each-result-icon
|
|
224
|
+
,.processing-details.success .processing-result-icon
|
|
312
225
|
{
|
|
313
|
-
|
|
314
|
-
font-style: italic;
|
|
315
|
-
font-size: 11px;
|
|
316
|
-
color: var(--text-placeholder);
|
|
226
|
+
--icon-size: 8px;
|
|
317
227
|
}
|
|
318
|
-
.
|
|
228
|
+
.hook.fail .before-each-result-icon
|
|
229
|
+
,.hook.fail .after-each-result-icon
|
|
230
|
+
,.processing-details.fail .processing-result-icon
|
|
319
231
|
{
|
|
320
|
-
|
|
232
|
+
--icon-size: 12px;
|
|
321
233
|
}
|
|
322
|
-
.before-result
|
|
323
|
-
,.after-result
|
|
234
|
+
.hook:is(.running) .before-each-result-icon::before
|
|
235
|
+
,.hook:is(.running) .after-each-result-icon::before
|
|
236
|
+
,.processing-details:is(.running) .processing-result-icon::before
|
|
237
|
+
{
|
|
238
|
+
--icon-size: 9px;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* Hook Display */
|
|
242
|
+
.hook
|
|
324
243
|
{
|
|
325
244
|
display: none;
|
|
326
245
|
}
|
|
246
|
+
:host(.has-before-all-hook) #before-all-details
|
|
247
|
+
,:host(.has-after-all-hook) #after-all-details
|
|
248
|
+
{
|
|
249
|
+
display: initial;
|
|
250
|
+
}
|
|
251
|
+
:host(.has-before-each-hook) .before-each-details
|
|
252
|
+
,:host(.has-after-each-hook) .after-each-details
|
|
253
|
+
{
|
|
254
|
+
display: initial;
|
|
255
|
+
}
|
|
256
|
+
:host(.has-required-before-hook) #required-before-any-details
|
|
257
|
+
,:host(.has-required-after-hook) #required-after-any-details
|
|
258
|
+
{
|
|
259
|
+
display: initial;
|
|
260
|
+
}
|
|
327
261
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
,.before-result
|
|
331
|
-
,.after-result
|
|
262
|
+
/* Test Display */
|
|
263
|
+
code-test .results
|
|
332
264
|
{
|
|
333
|
-
|
|
265
|
+
display: grid;
|
|
266
|
+
gap: var(--gap-small);
|
|
267
|
+
padding-inline-start: 1em;
|
|
334
268
|
}
|
|
335
269
|
|
|
336
|
-
|
|
270
|
+
code-test .results details .result
|
|
271
|
+
,.hook > .results
|
|
337
272
|
{
|
|
338
|
-
margin:
|
|
273
|
+
margin-inline-start: 1em;
|
|
339
274
|
}
|
|
340
275
|
|
|
341
|
-
.
|
|
276
|
+
.result.message:empty
|
|
342
277
|
{
|
|
343
|
-
|
|
344
|
-
min-width: auto;
|
|
345
|
-
max-width: auto;
|
|
346
|
-
appearance: none;
|
|
347
|
-
display: inline-flex;
|
|
348
|
-
justify-content: center;
|
|
349
|
-
align-items: center;
|
|
350
|
-
padding: 3px 10px 3px 7px;
|
|
351
|
-
font-size: 11px;
|
|
352
|
-
gap: var(--small-spacer);
|
|
353
|
-
border: var(--border-button);
|
|
354
|
-
background: var(--surface-button);
|
|
355
|
-
border-radius: 4px;
|
|
356
|
-
text-shadow: 1px 1px rgb(0 0 0 / .2);
|
|
357
|
-
color: var(--text-button);
|
|
278
|
+
padding: .5em 1em;
|
|
358
279
|
}
|
|
359
|
-
.
|
|
280
|
+
.result.message:empty::before
|
|
360
281
|
{
|
|
361
|
-
|
|
282
|
+
content: '[ this function has not been run ]';
|
|
283
|
+
font-family: monospace;
|
|
284
|
+
font-size: 12px;
|
|
285
|
+
font-style: italic;
|
|
362
286
|
}
|
|
363
|
-
|
|
287
|
+
|
|
288
|
+
/* Ordered Display */
|
|
289
|
+
#tests
|
|
364
290
|
{
|
|
365
|
-
|
|
291
|
+
counter-reset: tests;
|
|
366
292
|
}
|
|
367
|
-
|
|
293
|
+
code-test
|
|
368
294
|
{
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
295
|
+
counter-increment: tests;
|
|
296
|
+
}
|
|
297
|
+
code-test > details > summary > .description
|
|
298
|
+
{
|
|
299
|
+
flex: 1;
|
|
300
|
+
}
|
|
301
|
+
:host(:not([ordered="false"])) code-test > details > summary > .description::before
|
|
302
|
+
{
|
|
303
|
+
content: counter(tests) ". ";
|
|
376
304
|
}
|
|
377
305
|
|
|
306
|
+
/* Hook Name */
|
|
307
|
+
.hook-name,.processing-description
|
|
308
|
+
{
|
|
309
|
+
border-radius: 3px;
|
|
310
|
+
border: solid 1px;
|
|
311
|
+
/* background: rgb(0 0 0 / .2); */
|
|
312
|
+
font-family: monospace;
|
|
313
|
+
text-transform: uppercase;
|
|
314
|
+
font-size: 11px;
|
|
315
|
+
padding: 3px 7px;
|
|
316
|
+
}
|
|
378
317
|
|
|
379
|
-
|
|
318
|
+
#footer
|
|
319
|
+
{
|
|
320
|
+
display: flex;
|
|
321
|
+
justify-content: flex-end;
|
|
322
|
+
}
|
|
323
|
+
#group-results
|
|
380
324
|
{
|
|
381
|
-
:
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
325
|
+
display: flex;
|
|
326
|
+
gap: var(--gap);
|
|
327
|
+
padding: var(--gap);
|
|
328
|
+
}
|
|
385
329
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
border-color: oklch(35.02% 0.005 236.66);
|
|
394
|
-
}
|
|
395
|
-
:host(.running) .run[data-all]:hover
|
|
396
|
-
{
|
|
397
|
-
background-color: oklch(63.12% 0.004 219.55);
|
|
398
|
-
border-color:oklch(63.12% 0.004 219.55);
|
|
399
|
-
}
|
|
400
|
-
:host(.running) .run[data-all]:active
|
|
401
|
-
{
|
|
402
|
-
background-color: oklch(25.11% 0.006 258.36);
|
|
403
|
-
border-color: oklch(25.11% 0.006 258.36);
|
|
404
|
-
}
|
|
330
|
+
#passed-total-percent::before
|
|
331
|
+
{
|
|
332
|
+
content: '(';
|
|
333
|
+
}
|
|
334
|
+
#passed-total-percent::after
|
|
335
|
+
{
|
|
336
|
+
content: ')';
|
|
405
337
|
}
|
|
406
338
|
|
|
407
339
|
@keyframes spin
|
|
@@ -409,856 +341,1090 @@ pre
|
|
|
409
341
|
from { transform: rotate(0deg); }
|
|
410
342
|
to { transform: rotate(360deg); }
|
|
411
343
|
}`;
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}
|
|
424
|
-
async toBe(value, exact = false) {
|
|
425
|
-
const target = await this;
|
|
426
|
-
const result = exact == true ? target === value : target == value;
|
|
427
|
-
if (result == false) {
|
|
428
|
-
throw new Error(` Value is not equal.
|
|
429
|
-
Expected: ${value}
|
|
430
|
-
Result: ${target}`);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
async toContainText(value) {
|
|
434
|
-
const target = await this;
|
|
435
|
-
}
|
|
436
|
-
async toHaveAttribute(value) {
|
|
437
|
-
const target = await this;
|
|
438
|
-
if (!(target instanceof HTMLElement)) {
|
|
439
|
-
throw new Error("Unable to check for attribute on non-HTMLElement target");
|
|
440
|
-
}
|
|
441
|
-
if (target.getAttribute(value)) {
|
|
442
|
-
throw new Error("Taret does not have attribute");
|
|
443
|
-
}
|
|
444
|
-
}
|
|
344
|
+
const html = '<details id="component-details" class="details">\n <summary id="component-summary" class="summary">\n <svg class="icon arrow-icon"><use href="#icon-definition_arrow"></use></svg>\n <slot name="header">\n <header id="header">\n <span id="component-result-icon" class="result-icon"></span>\n <span id="title"><slot name="title"><span id="title-text">Tests</span></slot></span>\n <slot name="reload-button">\n <button type="button" id="reload-button" title="Reload">\n <slot name="reload-button-content">\n <slot name="reload-button-icon"><svg class="icon reset-icon reload-button-icon"><use href="#icon-definition_reset"></use></svg></slot>\n <slot name="reload-button-label"><span class="reload-button-label button-label label icon">Reload</span></slot>\n </slot>\n </button>\n </slot>\n <slot name="run-all-button">\n <button type="button" id="run-all-button" title="Run All Tests">\n <slot name="run-all-button-content">\n <slot name="run-all-button-icon"><svg class="icon arrow-icon run-button-icon run-all-button-icon"><use href="#icon-definition_arrow"></use></svg></slot>\n <slot name="run-all-button-label"><span class="run-all-button-label run-button-label button-label label icon">Run Tests</span></slot>\n </slot>\n </button>\n </slot>\n <slot name="header-details"></slot>\n </header>\n </slot>\n </summary>\n <div id="component-content" class="content">\n <details id="required-before-any-details" class="hook">\n <summary id="required-before-any-summary">\n <svg class="icon arrow-icon"><use href="#icon-definition_arrow"></use></svg>\n <span id="required-before-any-result-icon" class="result-icon"></span>\n <span id="required-before-any-description" class="description hook-name">Required Before Any Hook</span>\n </summary>\n <div class="results">\n <div id="required-before-any-results" class="result message"></div>\n </div>\n </details>\n <details id="before-all-details" class="hook">\n <summary id="before-all-summary">\n <svg class="icon arrow-icon"><use href="#icon-definition_arrow"></use></svg>\n <span id="before-all-result-icon" class="result-icon"></span>\n <span id="before-all-description" class="description hook-name">Before All Hook</span>\n </summary>\n <div class="results">\n <div id="before-all-results" class="result message"></div>\n </div>\n </details>\n <div id="tests"></div>\n <details id="after-all-details" class="hook">\n <summary id="after-all-summary">\n <svg class="icon arrow-icon"><use href="#icon-definition_arrow"></use></svg>\n <span id="after-all-result-icon" class="result-icon"></span>\n <span id="after-all-description" class="description hook-name">After All Hook</span>\n </summary>\n <div class="results">\n <div id="after-all-results" class="result message"></div>\n </div>\n </details>\n <details id="required-after-any-details" class="hook">\n <summary id="required-after-any-summary">\n <svg class="icon arrow-icon"><use href="#icon-definition_arrow"></use></svg>\n <span id="required-after-any-result-icon" class="result-icon"></span>\n <span id="required-after-any-description" class="description hook-name">Required After Any Hook</span>\n </summary>\n <div class="results">\n <div id="required-after-any-results" class="result message"></div>\n </div>\n </details>\n </div>\n \n <slot name="footer">\n <foooter id="footer">\n <span id="group-results">\n <span id="duration">\n <span id="duration-label">Duration</span>\n <span id="duration-value"></span>\n <span id="duration-unit">ms</span>\n </span>\n <span id="results-progress">\n <progress id="results-progress-value"></progress>\n </span>\n <span id="passed-total-pair">\n <span id="total-tests-passed-value"></span>\n <span id="passed-total-delimiter">of</span>\n <span id="total-tests-count-value"></span>\n <span id="total-tests-passed-label">Passed</span>\n </span>\n <span id="passed-total-percent">\n <span id="passed-total-percent-value"></span>\n <span id="passed-total-percent-label">%</span>\n </span>\n </span>\n </foooter>\n </slot>\n</details>\n<template id="prompt-template">\n <div class="prompt">\n <div class="prompt-display">\n <span class="icon prompt-icon"></span>\n <span class="label prompt-label"></span>\n </div>\n <div class="prompt-actions">\n <button class="prompt-button accept" type="button">Accept</button>\n <button class="prompt-button reject" type="button">Reject</button>\n </div>\n </div>\n</template>\n<div id="icon-definitions" style="display: none;">\n <svg id="icon-definition_arrow" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">\n <path d="m3.26,6.81l-2.93,-4.69c-0.37,-0.58 0.05,-1.34 0.74,-1.34l5.87,0c0.69,0 1.11,0.76 0.74,1.34l-2.93,4.69c-0.35,0.55 -1.14,0.55 -1.49,0z" fill="var(--fill-color, currentcolor)" />\n </svg>\n <svg id="icon-definition_reset" class="icon reset" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">\n <path\n style="fill:var(--fill-color, currentcolor);stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none;paint-order:markers stroke fill"\n d="M 5.484375 0.43359375 A 1.5224222 1.5224222 0 0 0 4.2558594 1.2011719 L 0.99804688 6.9453125 A 1.5224222 1.5224222 0 0 0 2.5488281 9.2011719 L 9.34375 8.171875 A 1.5224222 1.5224222 0 0 0 10.332031 5.7539062 L 9.4746094 4.6113281 C 11.949333 3.8016718 14.718209 4.258351 16.822266 5.9570312 C 19.510764 8.1275534 20.456787 11.785479 19.160156 14.988281 C 17.863527 18.191083 14.6405 20.15873 11.199219 19.847656 C 7.7579362 19.536584 4.9376009 17.022073 4.2363281 13.638672 A 1.5 1.5 0 0 0 2.4628906 12.474609 A 1.5 1.5 0 0 0 1.2988281 14.248047 C 2.2656928 18.912838 6.1831413 22.407052 10.927734 22.835938 C 15.672328 23.264824 20.153706 20.531029 21.941406 16.115234 C 23.729107 11.699441 22.413741 6.6156073 18.707031 3.6230469 C 16.853677 2.1267667 14.61485 1.3255701 12.347656 1.2324219 C 10.738216 1.1662975 9.1150542 1.4598646 7.6035156 2.1132812 L 6.7988281 1.0390625 A 1.5224222 1.5224222 0 0 0 5.484375 0.43359375 z " />\n </svg>\n <svg id="icon-definition_cancel" class="icon cancel" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">\n <path\n style="fill:var(--fill-color, currentcolor);stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none;paint-order:markers stroke fill"\n d="M -7.063234 9.5244002 C -5.8135728 7.6769245 -5.0820528 5.453265 -5.0820528 3.0633809 C -5.0820529 -3.3096433 -10.278145 -8.5098163 -16.65117 -8.5098163 C -23.024193 -8.5098163 -28.22385 -3.3110105 -28.22385 3.0620137 C -28.22385 9.4350379 -23.025043 14.634694 -16.65202 14.634694 C -12.668879 14.634694 -9.1460028 12.603526 -7.063234 9.5244002 z M -9.5406311 7.8637601 C -11.076991 10.143147 -13.683157 11.63463 -16.652974 11.63463 C -19.960499 11.63463 -22.814085 9.782061 -24.244824 7.0543029 L -24.236684 7.0527515 L -8.1332524 3.983715 L -8.1305391 3.9831979 C -8.2815631 5.4121635 -8.7798709 6.7350751 -9.5406311 7.8637601 z M -9.0610781 -0.92890828 L -9.069218 -0.92735695 L -25.17265 2.1416796 L -25.175363 2.1421967 C -24.719122 -2.1725739 -21.093311 -5.5092358 -16.652928 -5.5092358 C -13.345403 -5.5092358 -10.491243 -3.6566663 -9.0610781 -0.92890828 z "\n transform="rotate(-124.20981)" />\n </svg>\n</div>';
|
|
345
|
+
const CodeTestEvent = {
|
|
346
|
+
BeforeAll: "beforeall",
|
|
347
|
+
AfterAll: "afterall",
|
|
348
|
+
BeforeTest: "beforetest",
|
|
349
|
+
AfterTest: "aftertest",
|
|
350
|
+
BeforeHook: "beforehook",
|
|
351
|
+
AfterHook: "afterhook",
|
|
352
|
+
Cancel: "cancel",
|
|
353
|
+
Context: "context",
|
|
354
|
+
Reset: "reset"
|
|
445
355
|
};
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
return promise;
|
|
356
|
+
const COMPONENT_TAG_NAME$1 = "code-test";
|
|
357
|
+
class CodeTestElement extends HTMLElement {
|
|
358
|
+
state = {
|
|
359
|
+
testId: "",
|
|
360
|
+
description: "none",
|
|
361
|
+
isDisabled: false,
|
|
362
|
+
testState: void 0,
|
|
363
|
+
beforeEachState: void 0,
|
|
364
|
+
afterEachState: void 0
|
|
365
|
+
};
|
|
366
|
+
setState(state) {
|
|
367
|
+
this.state = state;
|
|
368
|
+
this.#render();
|
|
460
369
|
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
resolve(result);
|
|
466
|
-
return;
|
|
467
|
-
}
|
|
468
|
-
resolve(value);
|
|
370
|
+
setStateProperties(state) {
|
|
371
|
+
this.setState({
|
|
372
|
+
...this.state,
|
|
373
|
+
...state
|
|
469
374
|
});
|
|
470
|
-
return promise;
|
|
471
375
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
376
|
+
setTestStateProperties(key, state) {
|
|
377
|
+
if (this.state[key] == null) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
this.setState({
|
|
381
|
+
...this.state,
|
|
382
|
+
[key]: {
|
|
383
|
+
...this.state[key],
|
|
384
|
+
...state
|
|
478
385
|
}
|
|
479
|
-
resolve(value);
|
|
480
386
|
});
|
|
481
|
-
return promise;
|
|
482
387
|
}
|
|
483
|
-
|
|
484
|
-
return
|
|
485
|
-
const template = host.findElement("prompt-template");
|
|
486
|
-
const promptElement = _CodeTests.createElementFromTemplate(template);
|
|
487
|
-
promptElement.querySelector(".label").textContent = message;
|
|
488
|
-
const clickHandler = (event) => {
|
|
489
|
-
const composedPath = event.composedPath();
|
|
490
|
-
const acceptButton = composedPath.find((item) => item instanceof HTMLButtonElement && item.classList.contains("accept"));
|
|
491
|
-
if (acceptButton != null) {
|
|
492
|
-
const result = options?.onAccept?.() ?? true;
|
|
493
|
-
promptElement.removeEventListener("click", clickHandler);
|
|
494
|
-
resolve(result);
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
const rejectButton = composedPath.find((item) => item instanceof HTMLButtonElement && item.classList.contains("reject"));
|
|
498
|
-
if (rejectButton != null) {
|
|
499
|
-
const result = options?.onReject?.() ?? false;
|
|
500
|
-
promptElement.removeEventListener("click", clickHandler);
|
|
501
|
-
resolve(result);
|
|
502
|
-
return;
|
|
503
|
-
}
|
|
504
|
-
};
|
|
505
|
-
promptElement.addEventListener("click", clickHandler);
|
|
506
|
-
if (options?.acceptLabel != null) {
|
|
507
|
-
promptElement.querySelector(".accept").textContent = options.acceptLabel;
|
|
508
|
-
}
|
|
509
|
-
if (options?.rejectLabel != null) {
|
|
510
|
-
promptElement.querySelector(".reject").textContent = options.rejectLabel;
|
|
511
|
-
}
|
|
512
|
-
const details = parent instanceof HTMLDetailsElement ? parent : parent.querySelector(".test-details");
|
|
513
|
-
if (details != null) {
|
|
514
|
-
details.open = true;
|
|
515
|
-
}
|
|
516
|
-
parent.querySelector(".result")?.append(promptElement);
|
|
517
|
-
});
|
|
388
|
+
findElement(query) {
|
|
389
|
+
return this.querySelector(query);
|
|
518
390
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
if (templateNode == null) {
|
|
522
|
-
throw new Error(`Unable to find template element from selector: ${target}`);
|
|
523
|
-
}
|
|
524
|
-
const firstChild = templateNode.content.cloneNode(true).querySelector("*");
|
|
525
|
-
if (firstChild == null) {
|
|
526
|
-
throw new Error(`Unable to find first child of template element`);
|
|
527
|
-
}
|
|
528
|
-
parent?.append(firstChild);
|
|
529
|
-
return firstChild;
|
|
391
|
+
findElements(query) {
|
|
392
|
+
return Array.from(this.querySelectorAll(query));
|
|
530
393
|
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
return CodeTests.expect(value);
|
|
534
|
-
}
|
|
535
|
-
function prompt(host, parent, message, options) {
|
|
536
|
-
return CodeTests.prompt(host, parent, message, options);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
// node_modules/.pnpm/ce-part-utils@0.0.0/node_modules/ce-part-utils/dist/ce-part-utils.js
|
|
540
|
-
var DEFAULT_ELEMENT_SELECTOR = ":not(slot,defs,g,rect,path,circle,ellipse,line,polygon,text,tspan,use,svg image,svg title,desc,template,template *)";
|
|
541
|
-
function assignClassAndIdToPart(shadowRoot) {
|
|
542
|
-
const identifiedElements = [...shadowRoot.querySelectorAll(`${DEFAULT_ELEMENT_SELECTOR}[id]`)];
|
|
543
|
-
for (let i = 0; i < identifiedElements.length; i++) {
|
|
544
|
-
identifiedElements[i].part.add(identifiedElements[i].id);
|
|
394
|
+
isRunning() {
|
|
395
|
+
return this.state.testState?.isRunning == true || this.state.beforeEachState?.isRunning == true || this.state.afterEachState?.isRunning == true;
|
|
545
396
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
classedElements[i].part.add(...classedElements[i].classList);
|
|
397
|
+
hasRun() {
|
|
398
|
+
return this.state.testState?.hasRun == true || this.state.beforeEachState?.hasRun == true || this.state.afterEachState?.hasRun == true;
|
|
549
399
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
var COMPONENT_TAG_NAME = "code-tests";
|
|
574
|
-
var CodeTestsElement = class extends HTMLElement {
|
|
575
|
-
componentParts = /* @__PURE__ */ new Map();
|
|
576
|
-
getElement(id) {
|
|
577
|
-
if (this.componentParts.get(id) == null) {
|
|
578
|
-
const part = this.findElement(id);
|
|
579
|
-
if (part != null) {
|
|
580
|
-
this.componentParts.set(id, part);
|
|
400
|
+
resultCategory() {
|
|
401
|
+
const testCategory = this.state.testState?.resultCategory ?? "none";
|
|
402
|
+
const beforeEachCategory = this.state.beforeEachState?.resultCategory ?? "none";
|
|
403
|
+
const afterEachCategory = this.state.afterEachState?.resultCategory ?? "none";
|
|
404
|
+
if (testCategory == "none" && beforeEachCategory == "none" && afterEachCategory == "none") {
|
|
405
|
+
return "none";
|
|
406
|
+
}
|
|
407
|
+
if (this.state.beforeEachState == null && this.state.afterEachState == null) {
|
|
408
|
+
return testCategory;
|
|
409
|
+
} else if (this.state.beforeEachState != null && this.state.afterEachState == null) {
|
|
410
|
+
if (testCategory == "fail" || beforeEachCategory == "fail") {
|
|
411
|
+
return "fail";
|
|
412
|
+
}
|
|
413
|
+
if (testCategory == "success" && beforeEachCategory == "success") {
|
|
414
|
+
return "success";
|
|
415
|
+
}
|
|
416
|
+
return "none";
|
|
417
|
+
} else if (this.state.beforeEachState == null && this.state.afterEachState != null) {
|
|
418
|
+
if (testCategory == "fail" || afterEachCategory == "fail") {
|
|
419
|
+
return "fail";
|
|
420
|
+
}
|
|
421
|
+
if (testCategory == "success" && afterEachCategory == "success") {
|
|
422
|
+
return "success";
|
|
581
423
|
}
|
|
424
|
+
return "none";
|
|
425
|
+
} else if (this.state.beforeEachState != null && this.state.afterEachState != null) {
|
|
426
|
+
if (testCategory == "fail" || beforeEachCategory == "fail" || afterEachCategory == "fail") {
|
|
427
|
+
return "fail";
|
|
428
|
+
}
|
|
429
|
+
if (testCategory == "success" && beforeEachCategory == "success" && afterEachCategory == "success") {
|
|
430
|
+
return "success";
|
|
431
|
+
}
|
|
432
|
+
return "none";
|
|
582
433
|
}
|
|
583
|
-
return this.componentParts.get(id);
|
|
584
|
-
}
|
|
585
|
-
findElement(id) {
|
|
586
|
-
return this.shadowRoot.getElementById(id);
|
|
587
|
-
}
|
|
588
|
-
#hooks = {};
|
|
589
|
-
#continueRunningTests = true;
|
|
590
|
-
constructor() {
|
|
591
|
-
super();
|
|
592
|
-
this.attachShadow({ mode: "open" });
|
|
593
|
-
this.shadowRoot.innerHTML = code_tests_default2;
|
|
594
|
-
this.shadowRoot.adoptedStyleSheets.push(COMPONENT_STYLESHEET);
|
|
595
|
-
this.#boundClickHandler = this.#onClick.bind(this);
|
|
596
434
|
}
|
|
597
435
|
connectedCallback() {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
436
|
+
this.#render();
|
|
437
|
+
}
|
|
438
|
+
#render() {
|
|
439
|
+
const resultMessage = this.state.testState == null ? "" : typeof this.state.testState.resultContent == "boolean" ? this.state.testState.resultContent == true ? `<code class="code" part="code"><pre class="pre success-message" part="pre success-message">Passed</pre></code>` : `<code class="code" part="code"><pre class="pre error-message" part="pre error-message">Failed</pre></code>` : typeof this.state.testState.resultContent == "number" ? `<code class="code" part="code"><pre class="pre success-message" part="pre success-message">Passed: ${this.state.testState.resultContent.toString()}</pre></code>` : typeof this.state.testState.resultContent == "string" ? this.state.testState.resultContent : "";
|
|
440
|
+
this.innerHTML = `<details class="test-details" part="test-details" ${this.isRunning() == true || this.hasRun() == true ? " open" : ""}>
|
|
441
|
+
<summary class="test-summary" part="test-summary">
|
|
442
|
+
<svg class="icon arrow-icon"><use href="#icon-definition_arrow"></use></svg>
|
|
443
|
+
<div class="result-icon test-result-icon${this.state.testState?.resultCategory != "none" ? ` ${this.state.testState?.resultCategory}` : ""}" part="result-icon"></div>
|
|
444
|
+
<span class="test-description description">${this.state.description}</span>
|
|
445
|
+
${this.state.testState?.duration != null && this.state.testState.duration > 0 ? `<span class="test-duration duration">
|
|
446
|
+
<span class="test-duration-value">${this.state.testState.duration > 10 ? this.state.testState.duration.toFixed(0) : this.state.testState.duration.toFixed(2)}</span>
|
|
447
|
+
<span class="test-duration-unit">ms</span>
|
|
448
|
+
</span>` : ""}
|
|
449
|
+
<button type="button" class="run-test-button" part="run-test-button" title="Run Test"${this.state.isDisabled == true ? " disabled" : ""}>
|
|
450
|
+
<slot name="run-button-content">
|
|
451
|
+
<slot name="run-button-icon"><svg class="icon arrow-icon run-button-icon"><use href="#icon-definition_arrow"></use></svg></slot>
|
|
452
|
+
<slot name="run-button-label"><span class="run-button-label button-label label icon">Run Test</span></slot>
|
|
453
|
+
</slot>
|
|
454
|
+
</button>
|
|
455
|
+
</summary>
|
|
456
|
+
<div class="results" part="results">
|
|
457
|
+
${this.state.beforeEachState == null ? "" : `<details class="before-each-details hook${this.state.beforeEachState.resultCategory == "none" ? "" : ` ${this.state.beforeEachState.resultCategory}`}${this.state.beforeEachState.isRunning == true ? " running" : ""}" part="before-each-details hook">
|
|
458
|
+
<summary class="before-each-summary" part="before-each-summary">
|
|
459
|
+
<svg class="icon arrow-icon"><use href="#icon-definition_arrow"></use></svg>
|
|
460
|
+
<div class="before-each-result-icon result-icon${this.state.beforeEachState.resultCategory != "none" ? ` ${this.state.beforeEachState.resultCategory}` : ""}" part="before-each-result-icon"></div>
|
|
461
|
+
<span class="before-each-description description hook-name">Before Each Hook</span>
|
|
462
|
+
</summary>
|
|
463
|
+
<div class="before-each-result result message" part="before-each-result result message">${typeof this.state.beforeEachState.resultContent != "string" ? "" : this.state.beforeEachState.resultContent}</div>
|
|
464
|
+
</details>`}
|
|
465
|
+
${this.state.testState == null ? "" : this.state.beforeEachState == null && this.state.afterEachState == null ? `<div class="test-result result message" part="test-result result message">${resultMessage}</div>` : `<details class="processing-details${this.state.testState.resultCategory == "none" ? "" : ` ${this.state.testState.resultCategory}`}${this.state.testState.isRunning == true ? " running" : ""}" part="processing-details"${this.state.testState.hasRun == true ? " open" : ""}>
|
|
466
|
+
<summary class="processing-summary" part="processing-summary">
|
|
467
|
+
<svg class="icon arrow-icon"><use href="#icon-definition_arrow"></use></svg>
|
|
468
|
+
<div class="processing-result-icon result-icon${this.state.testState.resultCategory != "none" ? ` ${this.state.testState.resultCategory}` : ""}" part="processing-result-icon result-icon"></div>
|
|
469
|
+
<span class="processing-description description">Test</span>
|
|
470
|
+
</summary>
|
|
471
|
+
<div class="test-result result message" part="test-result result message">${resultMessage}</div>
|
|
472
|
+
</details>`}
|
|
473
|
+
${this.state.afterEachState == null ? "" : `<details class="after-each-details hook${this.state.afterEachState.resultCategory == "none" ? "" : ` ${this.state.afterEachState.resultCategory}`}${this.state.afterEachState.isRunning == true ? " running" : ""}" part="after-each-detail hooks">
|
|
474
|
+
<summary class="after-each-summary" part="after-each-summary">
|
|
475
|
+
<svg class="icon arrow-icon"><use href="#icon-definition_arrow"></use></svg>
|
|
476
|
+
<div class="after-each-result-icon result-icon${this.state.afterEachState.resultCategory != "none" ? ` ${this.state.afterEachState.resultCategory}` : ""}" part="before-each-result-icon"></div>
|
|
477
|
+
<span class="after-each-description description hook-name">After Each Hook</span>
|
|
478
|
+
</summary>
|
|
479
|
+
<div class="after-each-result result message" part="after-each-result result message">${typeof this.state.afterEachState.resultContent != "string" ? "" : this.state.afterEachState.resultContent}</div>
|
|
480
|
+
</details>`}
|
|
481
|
+
</div>
|
|
482
|
+
</details>`;
|
|
483
|
+
this.dataset.testId = this.state.testId;
|
|
484
|
+
this.classList.add("test");
|
|
485
|
+
this.part.add("test");
|
|
486
|
+
this.toggleAttribute("success", this.resultCategory() == "success");
|
|
487
|
+
this.classList.toggle("success", this.resultCategory() == "success");
|
|
488
|
+
this.part.toggle("success", this.resultCategory() == "success");
|
|
489
|
+
this.classList.toggle("fail", this.resultCategory() == "fail");
|
|
490
|
+
this.part.toggle("fail", this.resultCategory() == "fail");
|
|
491
|
+
this.classList.toggle("running", this.isRunning());
|
|
492
|
+
this.part.toggle("running", this.isRunning());
|
|
493
|
+
if (this.state.beforeEachState?.resultContent instanceof HTMLElement) {
|
|
494
|
+
this.querySelector(".before-each-result").append(this.state.beforeEachState.resultContent);
|
|
602
495
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
496
|
+
if (this.state.testState?.resultContent instanceof HTMLElement) {
|
|
497
|
+
this.querySelector(".test-result").append(this.state.testState.resultContent);
|
|
498
|
+
}
|
|
499
|
+
if (this.state.afterEachState?.resultContent instanceof HTMLElement) {
|
|
500
|
+
this.querySelector(".after-each-result").append(this.state.afterEachState.resultContent);
|
|
606
501
|
}
|
|
607
|
-
this.loadTests(testsPath);
|
|
608
502
|
}
|
|
609
|
-
|
|
610
|
-
this.
|
|
503
|
+
enable() {
|
|
504
|
+
this.state.isDisabled = false;
|
|
505
|
+
this.findElement(".run-test-button").toggleAttribute("disabled", false);
|
|
611
506
|
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
507
|
+
disable() {
|
|
508
|
+
this.state.isDisabled = true;
|
|
509
|
+
this.findElement(".run-test-button").toggleAttribute("disabled", true);
|
|
510
|
+
}
|
|
511
|
+
async runTest(contextManager, testContext) {
|
|
512
|
+
if (this.state.testState?.test == null) {
|
|
616
513
|
return;
|
|
617
514
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
}
|
|
626
|
-
this.cancel();
|
|
627
|
-
} else {
|
|
628
|
-
this.runTests();
|
|
629
|
-
}
|
|
515
|
+
this.reset();
|
|
516
|
+
let testResult;
|
|
517
|
+
let stateProperties = {};
|
|
518
|
+
let duration = 0;
|
|
519
|
+
try {
|
|
520
|
+
if (contextManager.shouldContinueRunningTests == false) {
|
|
521
|
+
throw new Error("Tests have been disabled from continuing to run.");
|
|
630
522
|
}
|
|
631
|
-
|
|
523
|
+
const allowTest = this.dispatchEvent(new CustomEvent(CodeTestEvent.BeforeTest, { bubbles: true, cancelable: true, composed: true, detail: { testElement: this } }));
|
|
524
|
+
if (allowTest == false) {
|
|
525
|
+
throw new Error("Test has been prevented.");
|
|
526
|
+
}
|
|
527
|
+
if (testContext.codeTestsElement.state.isCanceled == true) {
|
|
528
|
+
throw new Error("Testing has been canceled.");
|
|
529
|
+
}
|
|
530
|
+
this.setTestStateProperties("testState", { isRunning: true });
|
|
531
|
+
contextManager.codeTestsElement.setState(contextManager.codeTestsElement.state);
|
|
532
|
+
const startTime = performance?.now() ?? Date.now();
|
|
533
|
+
testResult = await this.state.testState.test(testContext);
|
|
534
|
+
const endTime = performance?.now() ?? Date.now();
|
|
535
|
+
duration = endTime - startTime;
|
|
536
|
+
this.setTestStateProperties("testState", { isRunning: false, hasRun: true });
|
|
537
|
+
contextManager.codeTestsElement.setState(contextManager.codeTestsElement.state);
|
|
538
|
+
const testParsedResult = contextManager.parseTestResult(testResult, true);
|
|
539
|
+
stateProperties = {
|
|
540
|
+
testState: {
|
|
541
|
+
test: this.state.testState.test,
|
|
542
|
+
resultContent: testParsedResult.result,
|
|
543
|
+
resultCategory: testParsedResult.resultCategory,
|
|
544
|
+
hasRun: this.state.testState.hasRun,
|
|
545
|
+
isRunning: false,
|
|
546
|
+
duration
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
} catch (error) {
|
|
550
|
+
const errorParsedResult = contextManager.parseTestResult(testResult, false, error);
|
|
551
|
+
stateProperties = {
|
|
552
|
+
testState: {
|
|
553
|
+
test: this.state.testState.test,
|
|
554
|
+
resultContent: errorParsedResult.result,
|
|
555
|
+
resultCategory: errorParsedResult.resultCategory,
|
|
556
|
+
hasRun: this.state.testState.hasRun,
|
|
557
|
+
isRunning: false,
|
|
558
|
+
duration
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
console.error(error);
|
|
562
|
+
contextManager.shouldContinueRunningTests = false;
|
|
563
|
+
} finally {
|
|
564
|
+
this.setStateProperties({ ...stateProperties });
|
|
565
|
+
contextManager.codeTestsElement.setState(contextManager.codeTestsElement.state);
|
|
566
|
+
this.dispatchEvent(new CustomEvent(CodeTestEvent.AfterTest, { bubbles: true, cancelable: true, composed: true, detail: { testElement: this } }));
|
|
632
567
|
}
|
|
633
|
-
|
|
634
|
-
|
|
568
|
+
}
|
|
569
|
+
reset() {
|
|
570
|
+
const testState = this.state.testState != null ? {
|
|
571
|
+
resultCategory: "none",
|
|
572
|
+
resultContent: "",
|
|
573
|
+
test: this.state.testState.test,
|
|
574
|
+
hasRun: this.state.testState.hasRun,
|
|
575
|
+
isRunning: this.state.testState.isRunning,
|
|
576
|
+
duration: 0
|
|
577
|
+
} : void 0;
|
|
578
|
+
if (testState == void 0) {
|
|
635
579
|
return;
|
|
636
580
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
581
|
+
this.setTestStateProperties("testState", testState);
|
|
582
|
+
}
|
|
583
|
+
getMessageElement() {
|
|
584
|
+
return this.findElement(".test-result");
|
|
585
|
+
}
|
|
586
|
+
static observedAttributes = ["open"];
|
|
587
|
+
attributeChangedCallback(attributeName, _oldValue, newValue) {
|
|
588
|
+
if (attributeName == "open") {
|
|
589
|
+
this.findElement(".test-details").toggleAttribute("open", newValue != void 0);
|
|
640
590
|
}
|
|
641
|
-
this.isCanceled = false;
|
|
642
|
-
this.classList.remove("canceled");
|
|
643
|
-
this.part.remove("canceled");
|
|
644
|
-
this.#runTest(testId, test);
|
|
645
591
|
}
|
|
646
|
-
|
|
647
|
-
|
|
592
|
+
}
|
|
593
|
+
if (customElements.get(COMPONENT_TAG_NAME$1) == null) {
|
|
594
|
+
customElements.define(COMPONENT_TAG_NAME$1, CodeTestElement);
|
|
595
|
+
}
|
|
596
|
+
const NOTESTDEFINED = /* @__PURE__ */ Symbol("No Test Defined");
|
|
597
|
+
class ContextManager {
|
|
598
|
+
codeTestsElement;
|
|
599
|
+
// testContext?: TestContext;
|
|
600
|
+
constructor(parent) {
|
|
601
|
+
this.codeTestsElement = parent;
|
|
648
602
|
}
|
|
649
|
-
|
|
650
|
-
|
|
603
|
+
//#region Loading
|
|
604
|
+
async loadTests(path) {
|
|
651
605
|
if (path == null) {
|
|
652
606
|
return;
|
|
653
607
|
}
|
|
654
608
|
try {
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
const
|
|
660
|
-
const
|
|
661
|
-
const
|
|
662
|
-
const
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
const
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
if (tests == void 0) {
|
|
671
|
-
throw new Error(`Unable to find tests definition in file at path: ${path}`);
|
|
672
|
-
}
|
|
673
|
-
const beforeAll = tests["beforeall" /* BeforeAll */];
|
|
674
|
-
if (beforeAll != null) {
|
|
675
|
-
this.#hooks["beforeall" /* BeforeAll */] = beforeAll;
|
|
676
|
-
delete tests["beforeall" /* BeforeAll */];
|
|
677
|
-
this.classList.add("has-before-hook");
|
|
678
|
-
}
|
|
679
|
-
const afterAll = tests["afterall" /* AfterAll */];
|
|
680
|
-
if (afterAll != null) {
|
|
681
|
-
this.#hooks["afterall" /* AfterAll */] = afterAll;
|
|
682
|
-
delete tests["afterall" /* AfterAll */];
|
|
683
|
-
this.classList.add("has-after-hook");
|
|
684
|
-
}
|
|
685
|
-
const beforeEach = tests["beforeeach" /* BeforeEach */];
|
|
686
|
-
if (beforeEach != null) {
|
|
687
|
-
this.#hooks["beforeeach" /* BeforeEach */] = beforeEach;
|
|
688
|
-
delete tests["beforeeach" /* BeforeEach */];
|
|
689
|
-
}
|
|
690
|
-
const afterEach = tests["aftereach" /* AfterEach */];
|
|
691
|
-
if (afterEach != null) {
|
|
692
|
-
this.#hooks["aftereach" /* AfterEach */] = afterEach;
|
|
693
|
-
delete tests["aftereach" /* AfterEach */];
|
|
694
|
-
}
|
|
695
|
-
const requiredBeforeAny = tests["requiredbeforeany" /* RequiredBeforeAny */];
|
|
696
|
-
if (requiredBeforeAny != null) {
|
|
697
|
-
this.#hooks["requiredbeforeany" /* RequiredBeforeAny */] = requiredBeforeAny;
|
|
698
|
-
delete tests["requiredbeforeany" /* RequiredBeforeAny */];
|
|
699
|
-
this.classList.add("has-required-before-hook");
|
|
700
|
-
this.part.add("has-required-before-hook");
|
|
701
|
-
}
|
|
702
|
-
const requiredAfterAny = tests["requiredafterany" /* RequiredAfterAny */];
|
|
703
|
-
if (requiredAfterAny != null) {
|
|
704
|
-
this.#hooks["requiredafterany" /* RequiredAfterAny */] = requiredAfterAny;
|
|
705
|
-
delete tests["requiredafterany" /* RequiredAfterAny */];
|
|
706
|
-
this.classList.add("has-required-after-hook");
|
|
707
|
-
this.part.add("has-required-after-hook");
|
|
708
|
-
}
|
|
609
|
+
const { tests, hooks } = await this.#loadTests(path);
|
|
610
|
+
const beforeAll = hooks[Hook.BeforeAll];
|
|
611
|
+
const afterAll = hooks[Hook.AfterAll];
|
|
612
|
+
const beforeEach = hooks[Hook.BeforeEach];
|
|
613
|
+
const afterEach = hooks[Hook.AfterEach];
|
|
614
|
+
const requiredBeforeAny = hooks[Hook.RequiredBeforeAny];
|
|
615
|
+
const requiredAfterAny = hooks[Hook.RequiredAfterAny];
|
|
616
|
+
const beforeAllState = beforeAll == null ? void 0 : { resultCategory: "none", resultContent: "", test: beforeAll, hasRun: false, isRunning: false, duration: 0 };
|
|
617
|
+
const afterAllState = afterAll == null ? void 0 : { resultCategory: "none", resultContent: "", test: afterAll, hasRun: false, isRunning: false, duration: 0 };
|
|
618
|
+
const beforeEachState = beforeEach == null ? void 0 : { resultCategory: "none", resultContent: "", test: beforeEach, hasRun: false, isRunning: false, duration: 0 };
|
|
619
|
+
const afterEachState = afterEach == null ? void 0 : { resultCategory: "none", resultContent: "", test: afterEach, hasRun: false, isRunning: false, duration: 0 };
|
|
620
|
+
const requiredBeforeAnyState = requiredBeforeAny == null ? void 0 : { resultCategory: "none", resultContent: "", test: requiredBeforeAny, hasRun: false, isRunning: false, duration: 0 };
|
|
621
|
+
const requiredAfterAnyState = requiredAfterAny == null ? void 0 : { resultCategory: "none", resultContent: "", test: requiredAfterAny, hasRun: false, isRunning: false, duration: 0 };
|
|
622
|
+
this.codeTestsElement.state.beforeEachState = beforeEachState;
|
|
623
|
+
this.codeTestsElement.state.afterEachState = afterEachState;
|
|
709
624
|
for (const [description, test] of Object.entries(tests)) {
|
|
710
625
|
this.#addTest(description, test);
|
|
711
626
|
}
|
|
627
|
+
this.codeTestsElement.setStateProperties({
|
|
628
|
+
beforeAllState,
|
|
629
|
+
afterAllState,
|
|
630
|
+
beforeEachState,
|
|
631
|
+
afterEachState,
|
|
632
|
+
requiredBeforeAnyState,
|
|
633
|
+
requiredAfterAnyState,
|
|
634
|
+
resetHook: hooks.reset,
|
|
635
|
+
contextHook: hooks.context
|
|
636
|
+
});
|
|
712
637
|
} catch (error) {
|
|
713
|
-
|
|
638
|
+
console.error(error);
|
|
714
639
|
}
|
|
715
640
|
}
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
641
|
+
async #loadTests(path) {
|
|
642
|
+
const module = await this.#loadModule(path);
|
|
643
|
+
const tests = module.tests ?? module.default;
|
|
644
|
+
if (tests == void 0) {
|
|
645
|
+
throw new Error(`Unable to find tests definition in file at path: ${path}`);
|
|
646
|
+
}
|
|
647
|
+
const hooks = {};
|
|
648
|
+
const beforeAll = tests[Hook.BeforeAll];
|
|
649
|
+
if (beforeAll != null) {
|
|
650
|
+
hooks[Hook.BeforeAll] = beforeAll;
|
|
651
|
+
delete tests[Hook.BeforeAll];
|
|
652
|
+
}
|
|
653
|
+
const afterAll = tests[Hook.AfterAll];
|
|
654
|
+
if (afterAll != null) {
|
|
655
|
+
hooks[Hook.AfterAll] = afterAll;
|
|
656
|
+
delete tests[Hook.AfterAll];
|
|
657
|
+
}
|
|
658
|
+
const beforeEach = tests[Hook.BeforeEach];
|
|
659
|
+
if (beforeEach != null) {
|
|
660
|
+
hooks[Hook.BeforeEach] = beforeEach;
|
|
661
|
+
delete tests[Hook.BeforeEach];
|
|
662
|
+
}
|
|
663
|
+
const afterEach = tests[Hook.AfterEach];
|
|
664
|
+
if (afterEach != null) {
|
|
665
|
+
hooks[Hook.AfterEach] = afterEach;
|
|
666
|
+
delete tests[Hook.AfterEach];
|
|
667
|
+
}
|
|
668
|
+
const requiredBeforeAny = tests[Hook.RequiredBeforeAny];
|
|
669
|
+
if (requiredBeforeAny != null) {
|
|
670
|
+
hooks[Hook.RequiredBeforeAny] = requiredBeforeAny;
|
|
671
|
+
delete tests[Hook.RequiredBeforeAny];
|
|
672
|
+
}
|
|
673
|
+
const requiredAfterAny = tests[Hook.RequiredAfterAny];
|
|
674
|
+
if (requiredAfterAny != null) {
|
|
675
|
+
hooks[Hook.RequiredAfterAny] = requiredAfterAny;
|
|
676
|
+
delete tests[Hook.RequiredAfterAny];
|
|
677
|
+
}
|
|
678
|
+
const resetHook = tests[Hook.Reset];
|
|
679
|
+
if (resetHook != null) {
|
|
680
|
+
hooks[Hook.Reset] = resetHook;
|
|
681
|
+
delete tests[Hook.Reset];
|
|
682
|
+
}
|
|
683
|
+
const contextHook = tests[Hook.Context];
|
|
684
|
+
if (contextHook != null) {
|
|
685
|
+
hooks[Hook.Context] = contextHook;
|
|
686
|
+
delete tests[Hook.Context];
|
|
687
|
+
}
|
|
688
|
+
return { tests, hooks };
|
|
722
689
|
}
|
|
723
|
-
async
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
const
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
this
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
this
|
|
755
|
-
this.
|
|
756
|
-
this.
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
}
|
|
760
|
-
this.dispatchEvent(new CustomEvent("afterall" /* AfterAll */, { bubbles: true, composed: true }));
|
|
761
|
-
return;
|
|
690
|
+
async #loadModule(path) {
|
|
691
|
+
const lastSlashIndexInCurrentPath = window.location.href.lastIndexOf("/");
|
|
692
|
+
const currentPathHasExtension = window.location.href.substring(lastSlashIndexInCurrentPath).indexOf(".") != -1;
|
|
693
|
+
const currentPath = currentPathHasExtension == true ? window.location.href.substring(0, lastSlashIndexInCurrentPath + 1) : window.location.href;
|
|
694
|
+
const moduleDirectory = currentPath + path.substring(0, path.lastIndexOf("/") + 1);
|
|
695
|
+
const modulePath = currentPath + path;
|
|
696
|
+
let moduleContent = await (await fetch(modulePath)).text();
|
|
697
|
+
moduleContent = moduleContent.replaceAll(/['"`](((\.\/)|(\.\.\/))+(.*))['"`]/g, `'${moduleDirectory}$1'`);
|
|
698
|
+
const moduleFile = new File([moduleContent], path.substring(path.lastIndexOf("/")), { type: "text/javascript" });
|
|
699
|
+
const moduleURL = URL.createObjectURL(moduleFile);
|
|
700
|
+
const module = await import(
|
|
701
|
+
/* @vite-ignore */
|
|
702
|
+
moduleURL
|
|
703
|
+
);
|
|
704
|
+
return module;
|
|
705
|
+
}
|
|
706
|
+
#addTest(description, test) {
|
|
707
|
+
const testId = generateId();
|
|
708
|
+
const testElement = new CodeTestElement();
|
|
709
|
+
testElement.setStateProperties({
|
|
710
|
+
testId,
|
|
711
|
+
description,
|
|
712
|
+
testState: { test, resultCategory: "none", resultContent: "", isRunning: false, hasRun: false, duration: 0 },
|
|
713
|
+
beforeEachState: this.codeTestsElement.state.beforeEachState == null ? void 0 : {
|
|
714
|
+
isRunning: this.codeTestsElement.state.beforeEachState.isRunning,
|
|
715
|
+
hasRun: this.codeTestsElement.state.beforeEachState.hasRun,
|
|
716
|
+
resultCategory: this.codeTestsElement.state.beforeEachState.resultCategory,
|
|
717
|
+
resultContent: this.codeTestsElement.state.beforeEachState.resultContent,
|
|
718
|
+
duration: 0
|
|
719
|
+
},
|
|
720
|
+
afterEachState: this.codeTestsElement.state.afterEachState == null ? void 0 : {
|
|
721
|
+
isRunning: this.codeTestsElement.state.afterEachState.isRunning,
|
|
722
|
+
hasRun: this.codeTestsElement.state.afterEachState.hasRun,
|
|
723
|
+
resultCategory: this.codeTestsElement.state.afterEachState.resultCategory,
|
|
724
|
+
resultContent: this.codeTestsElement.state.afterEachState.resultContent,
|
|
725
|
+
duration: 0
|
|
762
726
|
}
|
|
727
|
+
});
|
|
728
|
+
this.codeTestsElement.findElement("#tests").append(testElement);
|
|
729
|
+
return testId;
|
|
730
|
+
}
|
|
731
|
+
//#endregion Loading
|
|
732
|
+
//#region Running
|
|
733
|
+
shouldContinueRunningTests = true;
|
|
734
|
+
async runTests(tests) {
|
|
735
|
+
const allowTests = this.codeTestsElement.dispatchEvent(new CustomEvent(CodeTestEvent.BeforeAll, { bubbles: true, composed: true, cancelable: true }));
|
|
736
|
+
if (allowTests == false) {
|
|
737
|
+
throw new Error("Tests have been prevented.");
|
|
763
738
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
} catch (error) {
|
|
779
|
-
this.#handleHookResult(hookResult, false, "before", false, error);
|
|
780
|
-
console.error(error);
|
|
781
|
-
this.#continueRunningTests = false;
|
|
782
|
-
this.classList.remove("running");
|
|
783
|
-
this.part.remove("running");
|
|
784
|
-
if (playButtonLabel != null) {
|
|
785
|
-
playButtonLabel.textContent = "Run Tests";
|
|
786
|
-
}
|
|
787
|
-
this.dispatchEvent(new CustomEvent("afterall" /* AfterAll */, { bubbles: true, composed: true }));
|
|
788
|
-
return;
|
|
789
|
-
}
|
|
739
|
+
await this.codeTestsElement.reset();
|
|
740
|
+
for (let i = 0; i < tests.length; i++) {
|
|
741
|
+
tests[i].disable();
|
|
742
|
+
}
|
|
743
|
+
const context = await this.createTestContext();
|
|
744
|
+
await this.runHook("requiredBeforeAnyState", void 0, context);
|
|
745
|
+
if (this.shouldContinueRunningTests == false) {
|
|
746
|
+
await this.#endTests(tests, context);
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
await this.runHook("beforeAllState", void 0, context);
|
|
750
|
+
if (this.shouldContinueRunningTests == false) {
|
|
751
|
+
await this.#endTests(tests, context);
|
|
752
|
+
return;
|
|
790
753
|
}
|
|
754
|
+
const inOrder = this.codeTestsElement.getAttribute("ordered") != "false";
|
|
791
755
|
if (inOrder == false) {
|
|
792
|
-
const promises =
|
|
793
|
-
for (const [id, test] of this.#tests) {
|
|
794
|
-
promises.push(this.#runTest(id, test));
|
|
795
|
-
}
|
|
756
|
+
const promises = tests.map((item) => this.runTest(item, true, context));
|
|
796
757
|
await Promise.all(promises);
|
|
797
758
|
} else {
|
|
798
|
-
for (
|
|
799
|
-
|
|
759
|
+
for (let i = 0; i < tests.length; i++) {
|
|
760
|
+
const test = tests[i];
|
|
761
|
+
if (this.shouldContinueRunningTests == false) {
|
|
800
762
|
break;
|
|
801
763
|
}
|
|
802
|
-
await this
|
|
764
|
+
await this.runTest(test, true, context);
|
|
803
765
|
}
|
|
804
766
|
}
|
|
805
|
-
if (this
|
|
806
|
-
this
|
|
807
|
-
this.part.remove("running");
|
|
808
|
-
if (playButtonLabel != null) {
|
|
809
|
-
playButtonLabel.textContent = "Run Tests";
|
|
810
|
-
}
|
|
811
|
-
this.dispatchEvent(new CustomEvent("afterall" /* AfterAll */, { bubbles: true, composed: true }));
|
|
767
|
+
if (this.shouldContinueRunningTests == false) {
|
|
768
|
+
await this.#endTests(tests, context);
|
|
812
769
|
return;
|
|
813
770
|
}
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
if (this.isCanceled == true) {
|
|
822
|
-
throw new Error("Test has been cancelled");
|
|
823
|
-
}
|
|
824
|
-
hookResult = await afterHook(this, afterAllHookElement);
|
|
825
|
-
this.#handleHookResult(hookResult, true, "after", false);
|
|
826
|
-
afterAllHookElement.part.remove("running");
|
|
827
|
-
afterAllHookElement.classList.remove("running");
|
|
828
|
-
} catch (error) {
|
|
829
|
-
this.#handleHookResult(hookResult, false, "after", false, error);
|
|
830
|
-
console.error(error);
|
|
831
|
-
const requiredAfterHook2 = this.#hooks["requiredafterany" /* RequiredAfterAny */];
|
|
832
|
-
if (requiredAfterHook2 != null) {
|
|
833
|
-
let hookResult2;
|
|
834
|
-
try {
|
|
835
|
-
const requiredAfterAnyHookElement = this.getElement(`required-after-any-details`);
|
|
836
|
-
requiredAfterAnyHookElement.classList.add("running");
|
|
837
|
-
requiredAfterAnyHookElement.part.add("running");
|
|
838
|
-
if (this.isCanceled == true) {
|
|
839
|
-
throw new Error("Test has been cancelled");
|
|
840
|
-
}
|
|
841
|
-
hookResult2 = await requiredAfterHook2(this, requiredAfterAnyHookElement);
|
|
842
|
-
this.#handleHookResult(hookResult2, true, "after", true);
|
|
843
|
-
requiredAfterAnyHookElement.part.remove("running");
|
|
844
|
-
requiredAfterAnyHookElement.classList.remove("running");
|
|
845
|
-
} catch (error2) {
|
|
846
|
-
this.#handleHookResult(hookResult2, false, "after", true, error2);
|
|
847
|
-
console.error(error2);
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
this.#continueRunningTests = false;
|
|
851
|
-
this.classList.remove("running");
|
|
852
|
-
this.part.remove("running");
|
|
853
|
-
if (playButtonLabel != null) {
|
|
854
|
-
playButtonLabel.textContent = "Run Tests";
|
|
855
|
-
}
|
|
856
|
-
this.dispatchEvent(new CustomEvent("afterall" /* AfterAll */, { bubbles: true, composed: true }));
|
|
857
|
-
return;
|
|
858
|
-
}
|
|
771
|
+
await this.runHook("afterAllState", void 0, context);
|
|
772
|
+
await this.#endTests(tests, context);
|
|
773
|
+
}
|
|
774
|
+
async #endTests(tests, context) {
|
|
775
|
+
await this.runHook("requiredAfterAnyState", void 0, context);
|
|
776
|
+
for (let i = 0; i < tests.length; i++) {
|
|
777
|
+
tests[i].enable();
|
|
859
778
|
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
requiredAfterAnyHookElement.classList.add("running");
|
|
866
|
-
requiredAfterAnyHookElement.part.add("running");
|
|
867
|
-
if (this.isCanceled == true) {
|
|
868
|
-
throw new Error("Test has been cancelled");
|
|
869
|
-
}
|
|
870
|
-
hookResult = await requiredAfterHook(this, requiredAfterAnyHookElement);
|
|
871
|
-
this.#handleHookResult(hookResult, true, "after", true);
|
|
872
|
-
requiredAfterAnyHookElement.part.remove("running");
|
|
873
|
-
requiredAfterAnyHookElement.classList.remove("running");
|
|
874
|
-
} catch (error) {
|
|
875
|
-
this.#handleHookResult(hookResult, false, "after", true, error);
|
|
876
|
-
console.error(error);
|
|
877
|
-
this.#continueRunningTests = false;
|
|
878
|
-
}
|
|
779
|
+
this.codeTestsElement.dispatchEvent(new CustomEvent(CodeTestEvent.AfterAll, { bubbles: true, composed: true }));
|
|
780
|
+
}
|
|
781
|
+
async runTest(test, inLoop, testContext) {
|
|
782
|
+
if (test == null) {
|
|
783
|
+
return;
|
|
879
784
|
}
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
playButtonLabel.textContent = "Run Tests";
|
|
785
|
+
if (inLoop == false) {
|
|
786
|
+
const tests = this.codeTestsElement.findElements("code-test");
|
|
787
|
+
for (let i = 0; i < tests.length; i++) {
|
|
788
|
+
tests[i].disable();
|
|
789
|
+
}
|
|
886
790
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
if (testElement == null) {
|
|
893
|
-
this.#addProcessError(`Unable to find test element for test: ${testId}`);
|
|
791
|
+
testContext = testContext ?? await this.createTestContext(test);
|
|
792
|
+
if (inLoop == false) {
|
|
793
|
+
await this.runHook("requiredBeforeAnyState", void 0, testContext);
|
|
794
|
+
if (this.shouldContinueRunningTests == false) {
|
|
795
|
+
await this.#endTest(testContext, inLoop);
|
|
894
796
|
return;
|
|
895
797
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
798
|
+
}
|
|
799
|
+
await this.runHook("beforeEachState", test, testContext);
|
|
800
|
+
if (this.shouldContinueRunningTests == false) {
|
|
801
|
+
await this.#endTest(testContext, inLoop);
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
await test.runTest(this, testContext);
|
|
805
|
+
if (this.shouldContinueRunningTests == false) {
|
|
806
|
+
await this.#endTest(testContext, inLoop);
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
await this.runHook("afterEachState", test, testContext);
|
|
810
|
+
await this.#endTest(testContext, inLoop);
|
|
908
811
|
}
|
|
909
|
-
async #
|
|
910
|
-
|
|
911
|
-
if (testElement == null) {
|
|
912
|
-
this.#addProcessError(`Unable to find test element for test: ${testId}`);
|
|
812
|
+
async #endTest(context, inLoop) {
|
|
813
|
+
if (inLoop == true) {
|
|
913
814
|
return;
|
|
914
815
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
if (
|
|
927
|
-
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
if (detailsElement != null) {
|
|
931
|
-
detailsElement.open = false;
|
|
932
|
-
}
|
|
933
|
-
let beforeResult = NOTESTDEFINED;
|
|
934
|
-
let testResult;
|
|
935
|
-
let afterResult = NOTESTDEFINED;
|
|
936
|
-
let testType;
|
|
816
|
+
await this.runHook("requiredAfterAnyState", void 0, context);
|
|
817
|
+
const tests = this.codeTestsElement.findElements("code-test");
|
|
818
|
+
for (let i = 0; i < tests.length; i++) {
|
|
819
|
+
tests[i].enable();
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
async runHook(testStateName, test, testContext) {
|
|
823
|
+
const testState = this.codeTestsElement.state[testStateName];
|
|
824
|
+
if (testState == null) {
|
|
825
|
+
return NOTESTDEFINED;
|
|
826
|
+
}
|
|
827
|
+
if (this.codeTestsElement.state.isCanceled == true) {
|
|
828
|
+
return { success: false, value: "Testing has been canceled." };
|
|
829
|
+
}
|
|
830
|
+
let hookResult;
|
|
937
831
|
try {
|
|
938
|
-
|
|
939
|
-
if (handleRequiredTests == true) {
|
|
940
|
-
const requiredBeforeHook = this.#hooks["requiredbeforeany" /* RequiredBeforeAny */];
|
|
941
|
-
if (requiredBeforeHook != null) {
|
|
942
|
-
let hookResult;
|
|
943
|
-
try {
|
|
944
|
-
const requiredBeforeAnyHookElement = this.getElement(`required-before-any-details`);
|
|
945
|
-
requiredBeforeAnyHookElement.classList.add("running");
|
|
946
|
-
requiredBeforeAnyHookElement.part.add("running");
|
|
947
|
-
if (this.isCanceled == true) {
|
|
948
|
-
throw new Error("Test has been cancelled");
|
|
949
|
-
}
|
|
950
|
-
hookResult = await requiredBeforeHook(this, requiredBeforeAnyHookElement);
|
|
951
|
-
this.#handleHookResult(hookResult, true, "before", true);
|
|
952
|
-
requiredBeforeAnyHookElement.part.remove("running");
|
|
953
|
-
requiredBeforeAnyHookElement.classList.remove("running");
|
|
954
|
-
} catch (error) {
|
|
955
|
-
this.#handleHookResult(hookResult, true, "before", true, error);
|
|
956
|
-
console.error(error);
|
|
957
|
-
this.#continueRunningTests = false;
|
|
958
|
-
return;
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
if (this.#continueRunningTests == false) {
|
|
832
|
+
if (this.shouldContinueRunningTests == false && (testStateName != "requiredAfterAnyState" || this.codeTestsElement.getAttribute("required-after") == "error")) {
|
|
963
833
|
throw new Error("Tests have been disabled from continuing to run.");
|
|
964
834
|
}
|
|
965
|
-
if (
|
|
966
|
-
|
|
967
|
-
}
|
|
968
|
-
const beforeHook = this.#hooks["beforeeach" /* BeforeEach */];
|
|
969
|
-
if (beforeHook != null) {
|
|
970
|
-
beforeResult = await beforeHook(this, testElement);
|
|
971
|
-
}
|
|
972
|
-
if (this.isCanceled == true) {
|
|
973
|
-
throw new Error("Test has been cancelled");
|
|
974
|
-
}
|
|
975
|
-
testResult = await test(this, testElement);
|
|
976
|
-
if (this.isCanceled == true) {
|
|
977
|
-
throw new Error("Test has been cancelled");
|
|
978
|
-
}
|
|
979
|
-
const afterHook = this.#hooks["aftereach" /* AfterEach */];
|
|
980
|
-
if (afterHook != null) {
|
|
981
|
-
afterResult = await afterHook(this, testElement);
|
|
982
|
-
}
|
|
983
|
-
if (handleRequiredTests == true) {
|
|
984
|
-
const requiredAfterHook = this.#hooks["requiredafterany" /* RequiredAfterAny */];
|
|
985
|
-
if (requiredAfterHook != null) {
|
|
986
|
-
let hookResult;
|
|
987
|
-
try {
|
|
988
|
-
const requiredBeforeAnyHookElement = this.getElement(`required-before-any-details`);
|
|
989
|
-
requiredBeforeAnyHookElement.classList.add("running");
|
|
990
|
-
requiredBeforeAnyHookElement.part.add("running");
|
|
991
|
-
if (this.isCanceled == true) {
|
|
992
|
-
throw new Error("Test has been cancelled");
|
|
993
|
-
}
|
|
994
|
-
hookResult = await requiredAfterHook(this, requiredBeforeAnyHookElement);
|
|
995
|
-
this.#handleHookResult(hookResult, true, "after", true);
|
|
996
|
-
requiredBeforeAnyHookElement.part.remove("running");
|
|
997
|
-
requiredBeforeAnyHookElement.classList.remove("running");
|
|
998
|
-
} catch (error) {
|
|
999
|
-
this.#handleHookResult(hookResult, true, "after", true, error);
|
|
1000
|
-
console.error(error);
|
|
1001
|
-
this.#continueRunningTests = false;
|
|
1002
|
-
return;
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
835
|
+
if (test != null) {
|
|
836
|
+
test.setTestStateProperties(testStateName, { isRunning: true });
|
|
1005
837
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
838
|
+
this.codeTestsElement.setTestStateProperties(testStateName, { isRunning: true });
|
|
839
|
+
hookResult = await testState.test(testContext);
|
|
840
|
+
if (test != null) {
|
|
841
|
+
test.setTestStateProperties(testStateName, { isRunning: false, hasRun: true });
|
|
1009
842
|
}
|
|
1010
|
-
|
|
1011
|
-
this
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
843
|
+
this.codeTestsElement.setTestStateProperties(testStateName, { isRunning: false, hasRun: true });
|
|
844
|
+
const hookParsedResult = this.parseTestResult(hookResult, true, void 0);
|
|
845
|
+
if (test != null) {
|
|
846
|
+
test.setTestStateProperties(testStateName, {
|
|
847
|
+
resultCategory: hookParsedResult.resultCategory,
|
|
848
|
+
resultContent: hookParsedResult.result
|
|
849
|
+
});
|
|
1015
850
|
}
|
|
851
|
+
this.codeTestsElement.setTestStateProperties(testStateName, {
|
|
852
|
+
resultCategory: hookParsedResult.resultCategory,
|
|
853
|
+
resultContent: hookParsedResult.result
|
|
854
|
+
});
|
|
1016
855
|
} catch (error) {
|
|
1017
|
-
this.#handleTestResult(testElement, testResult, false, error, testType);
|
|
1018
856
|
console.error(error);
|
|
1019
|
-
this
|
|
857
|
+
this.shouldContinueRunningTests = false;
|
|
858
|
+
hookResult = { success: false, value: `Failed: ${error.message}` };
|
|
859
|
+
const errorParsedResult = this.parseTestResult(hookResult, false, error);
|
|
860
|
+
if (test != null) {
|
|
861
|
+
test.setTestStateProperties(
|
|
862
|
+
testStateName,
|
|
863
|
+
{
|
|
864
|
+
isRunning: false,
|
|
865
|
+
hasRun: true,
|
|
866
|
+
resultContent: errorParsedResult.result,
|
|
867
|
+
resultCategory: errorParsedResult.resultCategory
|
|
868
|
+
}
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
this.codeTestsElement.setTestStateProperties(testStateName, {
|
|
872
|
+
isRunning: false,
|
|
873
|
+
hasRun: true,
|
|
874
|
+
resultCategory: errorParsedResult.resultCategory,
|
|
875
|
+
resultContent: errorParsedResult.result
|
|
876
|
+
});
|
|
1020
877
|
} finally {
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
iconElement?.classList.remove("running");
|
|
1024
|
-
iconElement?.part.remove("running");
|
|
1025
|
-
this.dispatchEvent(new CustomEvent("aftertest" /* AfterTest */, { bubbles: true, cancelable: true, composed: true, detail: { testElement } }));
|
|
878
|
+
this.codeTestsElement.dispatchEvent(new CustomEvent(CodeTestEvent.AfterHook, { bubbles: true, composed: true, detail: hookResult }));
|
|
879
|
+
return hookResult;
|
|
1026
880
|
}
|
|
1027
881
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
const
|
|
1038
|
-
|
|
1039
|
-
|
|
882
|
+
//#endregion Running
|
|
883
|
+
//#region Utils
|
|
884
|
+
parseTestResult(result, finishedTest, error) {
|
|
885
|
+
if (result == NOTESTDEFINED) {
|
|
886
|
+
return { result: "", resultCategory: "none" };
|
|
887
|
+
}
|
|
888
|
+
if (result == void 0) {
|
|
889
|
+
const message = finishedTest == true ? "Passed" : `Failed${error != null ? `:
|
|
890
|
+
${error.message}` : ""}`;
|
|
891
|
+
const className = finishedTest == true ? "success-message" : "error-message";
|
|
892
|
+
return {
|
|
893
|
+
result: `<code class="code" part="code">
|
|
894
|
+
<pre class="pre ${className}" part="pre ${className}">${message}</pre>
|
|
895
|
+
</code>`,
|
|
896
|
+
resultCategory: finishedTest == true ? "success" : "fail"
|
|
897
|
+
};
|
|
898
|
+
} else if (typeof result == "boolean") {
|
|
899
|
+
return { result, resultCategory: result == true ? "success" : "fail" };
|
|
900
|
+
} else if (typeof result == "function") {
|
|
901
|
+
console.log("function");
|
|
902
|
+
return { result: `[A function was returned]`, resultCategory: "none" };
|
|
903
|
+
} else if (result instanceof HTMLElement || typeof result == "string") {
|
|
904
|
+
return { result, resultCategory: "none" };
|
|
1040
905
|
} else if (typeof result == "object") {
|
|
1041
906
|
const objectResult = result;
|
|
907
|
+
const className = finishedTest == true ? "success-message" : "error-message";
|
|
1042
908
|
if (objectResult.success != void 0 && objectResult.expected != void 0 && objectResult.value != void 0) {
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
`${objectResult.success == true ? `${trueMessage}:` : `${falseMessage}:`}
|
|
909
|
+
return {
|
|
910
|
+
result: `<code class="code" part="code">
|
|
911
|
+
<pre class="pre ${className}" part="pre ${className}">${objectResult.success == true ? "Passed" : "Failed"}
|
|
1047
912
|
Expected:${objectResult.expected}
|
|
1048
|
-
Result:${objectResult.value}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
913
|
+
Result:${objectResult.value}</pre>
|
|
914
|
+
</code>`,
|
|
915
|
+
resultCategory: objectResult.success == true ? "success" : "fail"
|
|
916
|
+
};
|
|
917
|
+
} else if (objectResult.success != void 0) {
|
|
918
|
+
return {
|
|
919
|
+
result: `<code class="code" part="code">
|
|
920
|
+
<pre class="pre ${className}" part="pre ${className}">${JSON.stringify(result, void 0, 2)}</pre>
|
|
921
|
+
</code>`,
|
|
922
|
+
resultCategory: objectResult.success == true ? "success" : "fail"
|
|
923
|
+
};
|
|
924
|
+
} else {
|
|
925
|
+
const className2 = finishedTest == true ? "success-message" : "error-message";
|
|
926
|
+
return {
|
|
927
|
+
result: `<code class="code" part="code">
|
|
928
|
+
<pre class="pre ${className2}" part="pre ${className2}">${JSON.stringify(result, void 0, 2)}</pre>
|
|
929
|
+
</code>`,
|
|
930
|
+
resultCategory: finishedTest == true ? "success" : "fail"
|
|
931
|
+
};
|
|
1053
932
|
}
|
|
1054
933
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
934
|
+
throw new Error("Unable to parse result type: Unknown result type");
|
|
935
|
+
}
|
|
936
|
+
async createTestContext(testElement) {
|
|
937
|
+
const context = {
|
|
938
|
+
detail: {},
|
|
939
|
+
codeTestsElement: this.codeTestsElement,
|
|
940
|
+
testElement,
|
|
941
|
+
messageElement: testElement?.findElement(".message")
|
|
942
|
+
};
|
|
943
|
+
if (this.codeTestsElement.state.contextHook != null) {
|
|
944
|
+
await this.codeTestsElement.state.contextHook(context);
|
|
1058
945
|
}
|
|
946
|
+
this.codeTestsElement.dispatchEvent(new CustomEvent(CodeTestEvent.Context, { bubbles: true, composed: true, detail: { context } }));
|
|
947
|
+
return context;
|
|
1059
948
|
}
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
defaultResult = this.#createDefaultResult(
|
|
1077
|
-
`${objectResult.success == true ? "Success:" : "Fail:"}
|
|
1078
|
-
Expected:${objectResult.expected}
|
|
1079
|
-
Result:${objectResult.value}`,
|
|
1080
|
-
objectResult.success
|
|
1081
|
-
);
|
|
1082
|
-
this.#setHookResult(defaultResult, finishedTest, beforeOrAfter, required);
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
949
|
+
//#endregion Utils
|
|
950
|
+
}
|
|
951
|
+
function generateId() {
|
|
952
|
+
const rnd = new Uint8Array(20);
|
|
953
|
+
crypto.getRandomValues(rnd);
|
|
954
|
+
const b64 = [].slice.apply(rnd).map(function(ch) {
|
|
955
|
+
return String.fromCharCode(ch);
|
|
956
|
+
}).join("");
|
|
957
|
+
const secret = btoa(b64).replace(/\//g, "_").replace(/\+/g, "-").replace(/=/g, "");
|
|
958
|
+
return secret;
|
|
959
|
+
}
|
|
960
|
+
class TestPromise extends Promise {
|
|
961
|
+
async toBeDefined(valueName) {
|
|
962
|
+
const target = await this;
|
|
963
|
+
if (target == void 0) {
|
|
964
|
+
throw new Error(`${valueName != null ? valueName : "Value"} is undefined`);
|
|
1085
965
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
966
|
+
}
|
|
967
|
+
async toBe(value, exact = false) {
|
|
968
|
+
const target = await this;
|
|
969
|
+
const result = exact == true ? target === value : target == value;
|
|
970
|
+
if (result == false) {
|
|
971
|
+
throw new Error(` Value is not equal.
|
|
972
|
+
Expected: ${value}
|
|
973
|
+
Result: ${target}`);
|
|
1089
974
|
}
|
|
1090
975
|
}
|
|
1091
|
-
|
|
1092
|
-
const
|
|
1093
|
-
|
|
976
|
+
async toContainText(value) {
|
|
977
|
+
const target = await this;
|
|
978
|
+
if (target instanceof HTMLElement) {
|
|
979
|
+
return { success: target.textContent.includes(value), index: target.textContent.indexOf(value) };
|
|
980
|
+
}
|
|
981
|
+
if (typeof target != "string") {
|
|
982
|
+
return false;
|
|
983
|
+
}
|
|
984
|
+
return { success: target.includes(value), index: target.indexOf(value) };
|
|
1094
985
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
986
|
+
async toHaveAttribute(value) {
|
|
987
|
+
const target = await this;
|
|
988
|
+
if (!(target instanceof HTMLElement)) {
|
|
989
|
+
throw new Error("Unable to check for attribute on non-HTMLElement target");
|
|
990
|
+
}
|
|
991
|
+
if (target.getAttribute(value)) {
|
|
992
|
+
throw new Error("Target does not have attribute");
|
|
993
|
+
}
|
|
1102
994
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
summaryElement.part.add("test-summary");
|
|
1114
|
-
const resultIcon = document.createElement("div");
|
|
1115
|
-
resultIcon.classList.add("result-icon");
|
|
1116
|
-
resultIcon.part.add("result-icon");
|
|
1117
|
-
summaryElement.append(resultIcon);
|
|
1118
|
-
const descriptionElement = document.createElement("span");
|
|
1119
|
-
descriptionElement.classList.add("description", "test-description");
|
|
1120
|
-
descriptionElement.textContent = description;
|
|
1121
|
-
summaryElement.append(descriptionElement);
|
|
1122
|
-
const runButton = document.createElement("button");
|
|
1123
|
-
runButton.classList.add("run", "test-run");
|
|
1124
|
-
runButton.part.add("run", "test-run");
|
|
1125
|
-
runButton.textContent = "Run Test";
|
|
1126
|
-
runButton.title = "Run Test";
|
|
1127
|
-
summaryElement.append(runButton);
|
|
1128
|
-
const beforeResultElement = document.createElement("div");
|
|
1129
|
-
beforeResultElement.classList.add("before-result", "test-before-result");
|
|
1130
|
-
beforeResultElement.part.add("before-result", "test-before-result");
|
|
1131
|
-
const resultElement = document.createElement("div");
|
|
1132
|
-
resultElement.classList.add("result", "test-result");
|
|
1133
|
-
resultElement.part.add("result", "test-result");
|
|
1134
|
-
const afterResultElement = document.createElement("div");
|
|
1135
|
-
afterResultElement.classList.add("after-result", "test-after-result");
|
|
1136
|
-
afterResultElement.part.add("after-result", "test-after-result");
|
|
1137
|
-
detailsElement.append(summaryElement);
|
|
1138
|
-
detailsElement.append(beforeResultElement);
|
|
1139
|
-
detailsElement.append(resultElement);
|
|
1140
|
-
detailsElement.append(afterResultElement);
|
|
1141
|
-
testElement.append(detailsElement);
|
|
1142
|
-
return testElement;
|
|
995
|
+
}
|
|
996
|
+
const DEFAULT_ELEMENT_SELECTOR = ":not(slot,defs,g,rect,path,circle,ellipse,line,polygon,text,tspan,use,svg image,svg title,desc,template,template *)";
|
|
997
|
+
function assignClassAndIdToPart(shadowRoot) {
|
|
998
|
+
assignIdToPart(shadowRoot);
|
|
999
|
+
assignClassToPart(shadowRoot);
|
|
1000
|
+
}
|
|
1001
|
+
function assignIdToPart(shadowRoot) {
|
|
1002
|
+
const identifiedElements = [...shadowRoot.querySelectorAll(`${DEFAULT_ELEMENT_SELECTOR}[id]`)];
|
|
1003
|
+
for (let i = 0; i < identifiedElements.length; i++) {
|
|
1004
|
+
identifiedElements[i].part.add(identifiedElements[i].id);
|
|
1143
1005
|
}
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1006
|
+
}
|
|
1007
|
+
function assignClassToPart(shadowRoot) {
|
|
1008
|
+
const classedElements = [...shadowRoot.querySelectorAll(`${DEFAULT_ELEMENT_SELECTOR}[class]`)];
|
|
1009
|
+
for (let i = 0; i < classedElements.length; i++) {
|
|
1010
|
+
classedElements[i].part.add(...classedElements[i].classList);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
const Hook = {
|
|
1014
|
+
BeforeAll: "beforeall",
|
|
1015
|
+
AfterAll: "afterall",
|
|
1016
|
+
BeforeEach: "beforeeach",
|
|
1017
|
+
AfterEach: "aftereach",
|
|
1018
|
+
RequiredBeforeAny: "requiredbeforeany",
|
|
1019
|
+
RequiredAfterAny: "requiredafterany",
|
|
1020
|
+
Reset: "reset",
|
|
1021
|
+
Context: "context"
|
|
1022
|
+
};
|
|
1023
|
+
const COMPONENT_STYLESHEET = new CSSStyleSheet();
|
|
1024
|
+
COMPONENT_STYLESHEET.replaceSync(style);
|
|
1025
|
+
const COMPONENT_TAG_NAME = "code-tests";
|
|
1026
|
+
class CodeTestsElement extends HTMLElement {
|
|
1027
|
+
state = {
|
|
1028
|
+
isCanceled: false,
|
|
1029
|
+
beforeAllState: void 0,
|
|
1030
|
+
afterAllState: void 0,
|
|
1031
|
+
beforeEachState: void 0,
|
|
1032
|
+
afterEachState: void 0,
|
|
1033
|
+
requiredBeforeAnyState: void 0,
|
|
1034
|
+
requiredAfterAnyState: void 0,
|
|
1035
|
+
resetHook: void 0,
|
|
1036
|
+
contextHook: void 0
|
|
1037
|
+
};
|
|
1038
|
+
setState(state) {
|
|
1039
|
+
this.state = state;
|
|
1040
|
+
this.#render();
|
|
1041
|
+
}
|
|
1042
|
+
setStateProperties(state) {
|
|
1043
|
+
this.setState({
|
|
1044
|
+
...this.state,
|
|
1045
|
+
...state
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
setTestStateProperties(key, state) {
|
|
1049
|
+
if (this.state[key] == null) {
|
|
1158
1050
|
return;
|
|
1159
1051
|
}
|
|
1160
|
-
|
|
1161
|
-
|
|
1052
|
+
this.setState({
|
|
1053
|
+
...this.state,
|
|
1054
|
+
[key]: {
|
|
1055
|
+
...this.state[key],
|
|
1056
|
+
...state
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
1162
1059
|
}
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
codeElement.classList.add("code");
|
|
1166
|
-
codeElement.part.add("code");
|
|
1167
|
-
const preElement = document.createElement("pre");
|
|
1168
|
-
preElement.textContent = message;
|
|
1169
|
-
const className = success == true ? "success-message" : "error-message";
|
|
1170
|
-
preElement.classList.add("pre", className);
|
|
1171
|
-
preElement.part.add("pre", className);
|
|
1172
|
-
codeElement.appendChild(preElement);
|
|
1173
|
-
return codeElement;
|
|
1060
|
+
findElement(query) {
|
|
1061
|
+
return this.shadowRoot.querySelector(query);
|
|
1174
1062
|
}
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
const detailsElement = this.getElement(`${selector}-details`);
|
|
1178
|
-
const resultsElement = this.getElement(`${selector}-results`);
|
|
1179
|
-
detailsElement.setAttribute("success", success == true ? "true" : "false");
|
|
1180
|
-
detailsElement.classList.toggle("success", success);
|
|
1181
|
-
detailsElement.part.toggle("success", success);
|
|
1182
|
-
detailsElement.classList.toggle("fail", !success);
|
|
1183
|
-
detailsElement.part.toggle("fail", !success);
|
|
1184
|
-
resultsElement.innerHTML = "";
|
|
1185
|
-
resultsElement.appendChild(valueElement);
|
|
1063
|
+
findElements(query) {
|
|
1064
|
+
return Array.from(this.shadowRoot.querySelectorAll(query));
|
|
1186
1065
|
}
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
${error.message}`;
|
|
1191
|
-
console.error(error);
|
|
1192
|
-
}
|
|
1193
|
-
const errorElement = document.createElement("li");
|
|
1194
|
-
errorElement.classList.add("error", "process-error");
|
|
1195
|
-
errorElement.part.add("error", "process-error");
|
|
1196
|
-
const codeElement = document.createElement("code");
|
|
1197
|
-
codeElement.classList.add("code", "process-error-code");
|
|
1198
|
-
codeElement.part.add("code", "process-error-code");
|
|
1199
|
-
const preElement = document.createElement("pre");
|
|
1200
|
-
preElement.classList.add("pre", "process-error-pre");
|
|
1201
|
-
preElement.part.add("pre", "process-error-pre");
|
|
1202
|
-
preElement.textContent = message;
|
|
1203
|
-
codeElement.append(preElement);
|
|
1204
|
-
errorElement.append(codeElement);
|
|
1205
|
-
this.getElement("tests").append(errorElement);
|
|
1066
|
+
getIsRunning() {
|
|
1067
|
+
const testsAreRunning = this.findElements("code-test").find((item) => item.isRunning() == true) != null;
|
|
1068
|
+
return testsAreRunning == true || this.state.requiredBeforeAnyState?.isRunning == true || this.state.requiredAfterAnyState?.isRunning == true || this.state.beforeAllState?.isRunning == true || this.state.afterAllState?.isRunning == true;
|
|
1206
1069
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
const
|
|
1210
|
-
if (
|
|
1211
|
-
return;
|
|
1070
|
+
getResultCategory() {
|
|
1071
|
+
const testCategory = this.findElements("code-test").reduce((result, item, _index) => {
|
|
1072
|
+
const category = item.resultCategory();
|
|
1073
|
+
if (result == "fail" || category == "fail") {
|
|
1074
|
+
return "fail";
|
|
1212
1075
|
}
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
if (items != null) {
|
|
1216
|
-
newList.append(...items);
|
|
1076
|
+
if ((result == "success" || result == "") && category == "success") {
|
|
1077
|
+
return "success";
|
|
1217
1078
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
} else {
|
|
1221
|
-
const list = this.shadowRoot.querySelector("ol");
|
|
1222
|
-
if (list == null) {
|
|
1223
|
-
return;
|
|
1079
|
+
if (category == "none") {
|
|
1080
|
+
return "none";
|
|
1224
1081
|
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1082
|
+
return "none";
|
|
1083
|
+
}, "");
|
|
1084
|
+
const states = [
|
|
1085
|
+
this.state.requiredBeforeAnyState,
|
|
1086
|
+
this.state.requiredAfterAnyState,
|
|
1087
|
+
this.state.beforeAllState,
|
|
1088
|
+
this.state.afterAllState
|
|
1089
|
+
];
|
|
1090
|
+
const statesCategory = states.reduce((result, item, _index) => {
|
|
1091
|
+
if (item == null) {
|
|
1092
|
+
return null;
|
|
1230
1093
|
}
|
|
1231
|
-
|
|
1094
|
+
const category = item?.resultCategory;
|
|
1095
|
+
if (result == "fail" || category == "fail") {
|
|
1096
|
+
return "fail";
|
|
1097
|
+
}
|
|
1098
|
+
if ((result == "success" || result == "") && category == "success") {
|
|
1099
|
+
return "success";
|
|
1100
|
+
}
|
|
1101
|
+
if (category == "none") {
|
|
1102
|
+
return "none";
|
|
1103
|
+
}
|
|
1104
|
+
return "none";
|
|
1105
|
+
}, "");
|
|
1106
|
+
if (testCategory == "none" && statesCategory == null) {
|
|
1107
|
+
return "none";
|
|
1108
|
+
} else if (testCategory == "fail" || statesCategory == "fail") {
|
|
1109
|
+
return "fail";
|
|
1110
|
+
} else if (testCategory == "success" && statesCategory == "success") {
|
|
1111
|
+
return "success";
|
|
1112
|
+
}
|
|
1113
|
+
return "none";
|
|
1114
|
+
}
|
|
1115
|
+
#contextManager;
|
|
1116
|
+
constructor() {
|
|
1117
|
+
super();
|
|
1118
|
+
this.attachShadow({ mode: "open" });
|
|
1119
|
+
this.shadowRoot.innerHTML = html;
|
|
1120
|
+
this.shadowRoot.adoptedStyleSheets.push(COMPONENT_STYLESHEET);
|
|
1121
|
+
}
|
|
1122
|
+
connectedCallback() {
|
|
1123
|
+
this.#init();
|
|
1124
|
+
}
|
|
1125
|
+
disconnectedCallback() {
|
|
1126
|
+
this.#destroy();
|
|
1127
|
+
}
|
|
1128
|
+
#isInitialized = false;
|
|
1129
|
+
async #init() {
|
|
1130
|
+
if (this.#isInitialized == true) {
|
|
1131
|
+
return;
|
|
1232
1132
|
}
|
|
1133
|
+
assignClassAndIdToPart(this.shadowRoot);
|
|
1134
|
+
this.addEventListener("click", this.#boundClickHandler);
|
|
1135
|
+
await new Promise((resolve) => requestAnimationFrame(() => {
|
|
1136
|
+
this.#contextManager = new ContextManager(this);
|
|
1137
|
+
resolve();
|
|
1138
|
+
}));
|
|
1139
|
+
this.#isInitialized = true;
|
|
1140
|
+
if (this.getAttribute("auto") == "false") {
|
|
1141
|
+
return;
|
|
1142
|
+
}
|
|
1143
|
+
this.reloadTests();
|
|
1144
|
+
}
|
|
1145
|
+
#destroy() {
|
|
1146
|
+
this.removeEventListener("click", this.#boundClickHandler);
|
|
1233
1147
|
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1148
|
+
#boundClickHandler = this.#onClick.bind(this);
|
|
1149
|
+
#onClick(event) {
|
|
1150
|
+
const runAllButton = event.composedPath().find((item) => item instanceof HTMLButtonElement && item.id == "run-all-button");
|
|
1151
|
+
if (runAllButton != null) {
|
|
1152
|
+
if (this.classList.contains("running")) {
|
|
1153
|
+
this.cancel();
|
|
1154
|
+
} else if (this.classList.contains("fail") || this.classList.contains("success")) {
|
|
1155
|
+
this.reset();
|
|
1239
1156
|
} else {
|
|
1240
|
-
this
|
|
1157
|
+
this.runTests();
|
|
1158
|
+
}
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
const reloadButton = event.composedPath().find((item) => item instanceof HTMLButtonElement && item.id == "reload-button");
|
|
1162
|
+
if (reloadButton != null) {
|
|
1163
|
+
this.reloadTests();
|
|
1164
|
+
}
|
|
1165
|
+
const runButton = event.composedPath().find((item) => item instanceof HTMLButtonElement && item.classList.contains("run-test-button"));
|
|
1166
|
+
if (runButton == null) {
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
const test = runButton.closest("code-test") ?? void 0;
|
|
1170
|
+
this.#contextManager.runTest(test, false);
|
|
1171
|
+
}
|
|
1172
|
+
#getCurrentTestsPath() {
|
|
1173
|
+
return this.getAttribute("src") ?? this.getAttribute("test") ?? this.getAttribute("tests") ?? this.getAttribute("run") ?? this.getAttribute("path") ?? void 0;
|
|
1174
|
+
}
|
|
1175
|
+
#render() {
|
|
1176
|
+
const isRunning = this.getIsRunning();
|
|
1177
|
+
const resultCategory = this.getResultCategory();
|
|
1178
|
+
const hasBeforeAllState = this.state.beforeAllState != null;
|
|
1179
|
+
const hasBeforeEachState = this.state.beforeEachState != null;
|
|
1180
|
+
const hasRequiredBeforeAnyState = this.state.requiredAfterAnyState != null;
|
|
1181
|
+
const hasAfterAllState = this.state.beforeAllState != null;
|
|
1182
|
+
const hasAfterEachState = this.state.beforeEachState != null;
|
|
1183
|
+
const hasRequiredAfterAnyState = this.state.requiredAfterAnyState != null;
|
|
1184
|
+
const hasBeforeHook = hasRequiredBeforeAnyState == true || hasBeforeAllState == true || hasBeforeEachState == true;
|
|
1185
|
+
const hasAfterHook = hasRequiredAfterAnyState == true || hasAfterAllState == true || hasAfterEachState == true;
|
|
1186
|
+
this.classList.toggle("canceled", this.state.isCanceled);
|
|
1187
|
+
this.part.toggle("canceled", this.state.isCanceled);
|
|
1188
|
+
this.classList.toggle("running", isRunning == true);
|
|
1189
|
+
this.part.toggle("running", isRunning == true);
|
|
1190
|
+
this.toggleAttribute("success", resultCategory == "success");
|
|
1191
|
+
this.classList.toggle("success", resultCategory == "success");
|
|
1192
|
+
this.part.toggle("success", resultCategory == "success");
|
|
1193
|
+
this.classList.toggle("fail", resultCategory == "fail");
|
|
1194
|
+
this.part.toggle("fail", resultCategory == "fail");
|
|
1195
|
+
this.classList.toggle("has-before-hook", hasBeforeHook);
|
|
1196
|
+
this.part.toggle("has-before-hook", hasBeforeHook);
|
|
1197
|
+
this.classList.toggle("has-after-hook", hasAfterHook);
|
|
1198
|
+
this.part.toggle("has-after-hook", hasAfterHook);
|
|
1199
|
+
this.classList.toggle("has-before-all-hook", hasBeforeAllState);
|
|
1200
|
+
this.part.toggle("has-before-all-hook", hasBeforeAllState);
|
|
1201
|
+
this.classList.toggle("has-after-all-hook", hasAfterAllState);
|
|
1202
|
+
this.part.toggle("has-after-all-hook", hasAfterAllState);
|
|
1203
|
+
this.classList.toggle("has-before-each-hook", hasBeforeEachState);
|
|
1204
|
+
this.part.toggle("has-before-each-hook", hasBeforeEachState);
|
|
1205
|
+
this.classList.toggle("has-after-each-hook", hasAfterEachState);
|
|
1206
|
+
this.part.toggle("has-after-each-hook", hasAfterEachState);
|
|
1207
|
+
this.classList.toggle("has-required-before-hook", hasRequiredBeforeAnyState);
|
|
1208
|
+
this.part.toggle("has-required-before-hook", hasRequiredBeforeAnyState);
|
|
1209
|
+
this.classList.toggle("has-required-after-hook", hasRequiredAfterAnyState);
|
|
1210
|
+
this.part.toggle("has-required-after-hook", hasRequiredAfterAnyState);
|
|
1211
|
+
const runAllButtonLabel = this.findElement(".run-all-button-label");
|
|
1212
|
+
if (runAllButtonLabel != null) {
|
|
1213
|
+
runAllButtonLabel.textContent = isRunning == true ? "Cancel" : resultCategory == "fail" ? "Reset" : "Run Tests";
|
|
1214
|
+
runAllButtonLabel.title = isRunning == true ? "Cancel the testing" : resultCategory == "fail" ? "Reset the tests so they can be run again" : "Run the tests";
|
|
1215
|
+
}
|
|
1216
|
+
const runAllIcon = this.findElement(".run-all-button-icon");
|
|
1217
|
+
if (runAllIcon != null) {
|
|
1218
|
+
runAllIcon.innerHTML = isRunning == true ? '<use href="#icon-definition_cancel"></use>' : resultCategory == "fail" ? '<use href="#icon-definition_reset"></use>' : '<use href="#icon-definition_arrow"></use>';
|
|
1219
|
+
}
|
|
1220
|
+
this.#renderHook(this.state.beforeAllState, "#before-all-results");
|
|
1221
|
+
this.#renderHook(this.state.afterAllState, "#after-all-results");
|
|
1222
|
+
this.#renderHook(this.state.requiredBeforeAnyState, "#required-before-any-results");
|
|
1223
|
+
this.#renderHook(this.state.requiredAfterAnyState, "#required-after-any-results");
|
|
1224
|
+
const title = this.findElement("#title");
|
|
1225
|
+
if (title != null) {
|
|
1226
|
+
title.textContent = this.getAttribute("label") ?? "Tests";
|
|
1227
|
+
}
|
|
1228
|
+
this.#renderGroupResults();
|
|
1229
|
+
}
|
|
1230
|
+
#renderHook(hookState, elementSelector) {
|
|
1231
|
+
const resultsElement = this.findElement(elementSelector);
|
|
1232
|
+
if (hookState?.resultContent instanceof HTMLElement) {
|
|
1233
|
+
resultsElement.append(hookState.resultContent);
|
|
1234
|
+
} else if (typeof hookState?.resultContent == "string") {
|
|
1235
|
+
resultsElement.innerHTML = hookState.resultContent;
|
|
1236
|
+
}
|
|
1237
|
+
const detailsElement = resultsElement.closest("details");
|
|
1238
|
+
detailsElement.toggleAttribute("open", hookState != void 0 && hookState.resultCategory != "none");
|
|
1239
|
+
detailsElement.classList.toggle("running", hookState?.isRunning == true);
|
|
1240
|
+
detailsElement.part.toggle("running", hookState?.isRunning == true);
|
|
1241
|
+
detailsElement.toggleAttribute("success", hookState?.resultCategory == "success");
|
|
1242
|
+
detailsElement.classList.toggle("success", hookState?.resultCategory == "success");
|
|
1243
|
+
detailsElement.part.toggle("success", hookState?.resultCategory == "success");
|
|
1244
|
+
detailsElement.classList.toggle("fail", hookState?.resultCategory == "fail");
|
|
1245
|
+
detailsElement.part.toggle("fail", hookState?.resultCategory == "fail");
|
|
1246
|
+
}
|
|
1247
|
+
#renderGroupResults() {
|
|
1248
|
+
const results = this.collectTestResults();
|
|
1249
|
+
const progress = this.findElement("#results-progress-value");
|
|
1250
|
+
if (progress != null) {
|
|
1251
|
+
progress.max = results.totalTests;
|
|
1252
|
+
progress.value = results.totalPassed;
|
|
1253
|
+
}
|
|
1254
|
+
const totalPassedElement = this.findElement("#total-tests-passed-value");
|
|
1255
|
+
if (totalPassedElement != null) {
|
|
1256
|
+
totalPassedElement.textContent = results.totalPassed.toString();
|
|
1257
|
+
}
|
|
1258
|
+
const totalTestsElement = this.findElement("#total-tests-count-value");
|
|
1259
|
+
if (totalTestsElement != null) {
|
|
1260
|
+
totalTestsElement.textContent = results.totalTests.toString();
|
|
1261
|
+
}
|
|
1262
|
+
const totalPercentElement = this.findElement("#passed-total-percent-value");
|
|
1263
|
+
if (totalPercentElement != null) {
|
|
1264
|
+
totalPercentElement.textContent = results.totalPercentage.toFixed(1);
|
|
1265
|
+
}
|
|
1266
|
+
const durationElement = this.findElement("#duration-value");
|
|
1267
|
+
if (durationElement != null) {
|
|
1268
|
+
durationElement.textContent = results.duration > 10 ? results.duration.toFixed(0) : results.duration.toFixed(2);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
collectTestResults() {
|
|
1272
|
+
const tests = this.findElements("code-test");
|
|
1273
|
+
const totalTests = tests.length;
|
|
1274
|
+
const totalPassed = tests.filter((item) => item.state.testState?.resultCategory == "success").length;
|
|
1275
|
+
const totalPercentage = totalTests == 0 ? 0 : totalPassed / totalTests * 100;
|
|
1276
|
+
const duration = tests.reduce((result, item, _index) => {
|
|
1277
|
+
return result + (item.state.testState?.duration ?? 0);
|
|
1278
|
+
}, 0);
|
|
1279
|
+
const results = {
|
|
1280
|
+
totalTests,
|
|
1281
|
+
totalPassed,
|
|
1282
|
+
totalPercentage,
|
|
1283
|
+
duration
|
|
1284
|
+
};
|
|
1285
|
+
return results;
|
|
1286
|
+
}
|
|
1287
|
+
async runTests() {
|
|
1288
|
+
const tests = this.findElements("code-test");
|
|
1289
|
+
return this.#contextManager.runTests(tests);
|
|
1290
|
+
}
|
|
1291
|
+
async reloadTests() {
|
|
1292
|
+
this.findElement("#tests").innerHTML = "";
|
|
1293
|
+
await this.reset();
|
|
1294
|
+
const testsPath = this.#getCurrentTestsPath();
|
|
1295
|
+
this.#contextManager.loadTests(testsPath);
|
|
1296
|
+
}
|
|
1297
|
+
async reset() {
|
|
1298
|
+
const tests = this.findElements("code-test");
|
|
1299
|
+
for (let i = 0; i < tests.length; i++) {
|
|
1300
|
+
const test = tests[i];
|
|
1301
|
+
const beforeEachState2 = this.state.beforeEachState != null ? {
|
|
1302
|
+
resultCategory: "none",
|
|
1303
|
+
resultContent: "",
|
|
1304
|
+
hasRun: this.state.beforeEachState.hasRun,
|
|
1305
|
+
isRunning: this.state.beforeEachState.isRunning,
|
|
1306
|
+
duration: 0
|
|
1307
|
+
} : void 0;
|
|
1308
|
+
const afterEachState2 = this.state.afterEachState != null ? {
|
|
1309
|
+
resultCategory: "none",
|
|
1310
|
+
resultContent: "",
|
|
1311
|
+
hasRun: this.state.afterEachState.hasRun,
|
|
1312
|
+
isRunning: this.state.afterEachState.isRunning,
|
|
1313
|
+
duration: 0
|
|
1314
|
+
} : void 0;
|
|
1315
|
+
if (beforeEachState2 != null) {
|
|
1316
|
+
test.state.beforeEachState = beforeEachState2;
|
|
1317
|
+
}
|
|
1318
|
+
if (afterEachState2 != null) {
|
|
1319
|
+
test.state.afterEachState = afterEachState2;
|
|
1320
|
+
}
|
|
1321
|
+
test.reset();
|
|
1322
|
+
}
|
|
1323
|
+
const beforeAllState = this.state.beforeAllState == void 0 ? void 0 : { resultContent: "", resultCategory: "none", test: this.state.beforeAllState.test, isRunning: false, hasRun: false, duration: 0 };
|
|
1324
|
+
const afterAllState = this.state.afterAllState == void 0 ? void 0 : { resultContent: "", resultCategory: "none", test: this.state.afterAllState.test, isRunning: false, hasRun: false, duration: 0 };
|
|
1325
|
+
const beforeEachState = this.state.beforeEachState == void 0 ? void 0 : { resultContent: "", resultCategory: "none", test: this.state.beforeEachState.test, isRunning: false, hasRun: false, duration: 0 };
|
|
1326
|
+
const afterEachState = this.state.afterEachState == void 0 ? void 0 : { resultContent: "", resultCategory: "none", test: this.state.afterEachState.test, isRunning: false, hasRun: false, duration: 0 };
|
|
1327
|
+
const requiredBeforeAnyState = this.state.requiredBeforeAnyState == void 0 ? void 0 : { resultContent: "", resultCategory: "none", test: this.state.requiredBeforeAnyState.test, isRunning: false, hasRun: false, duration: 0 };
|
|
1328
|
+
const requiredAfterAnyState = this.state.requiredAfterAnyState == void 0 ? void 0 : { resultContent: "", resultCategory: "none", test: this.state.requiredAfterAnyState.test, isRunning: false, hasRun: false, duration: 0 };
|
|
1329
|
+
this.setStateProperties({
|
|
1330
|
+
isCanceled: false,
|
|
1331
|
+
beforeAllState,
|
|
1332
|
+
afterAllState,
|
|
1333
|
+
beforeEachState,
|
|
1334
|
+
afterEachState,
|
|
1335
|
+
requiredAfterAnyState,
|
|
1336
|
+
requiredBeforeAnyState
|
|
1337
|
+
});
|
|
1338
|
+
this.#contextManager.shouldContinueRunningTests = true;
|
|
1339
|
+
if (this.state.resetHook != null) {
|
|
1340
|
+
await this.state.resetHook(await this.#contextManager.createTestContext());
|
|
1341
|
+
}
|
|
1342
|
+
this.dispatchEvent(new CustomEvent(CodeTestEvent.Reset, { bubbles: true, composed: true }));
|
|
1343
|
+
}
|
|
1344
|
+
cancel() {
|
|
1345
|
+
this.state.isCanceled = true;
|
|
1346
|
+
this.#contextManager.shouldContinueRunningTests = false;
|
|
1347
|
+
this.classList.add("canceled");
|
|
1348
|
+
this.part.add("canceled");
|
|
1349
|
+
this.dispatchEvent(new CustomEvent(CodeTestEvent.Cancel, { bubbles: true, composed: true }));
|
|
1350
|
+
}
|
|
1351
|
+
static observedAttributes = ["open", "label"];
|
|
1352
|
+
attributeChangedCallback(attributeName, _oldValue, newValue) {
|
|
1353
|
+
if (attributeName == "open") {
|
|
1354
|
+
this.findElement("#component-details").toggleAttribute("open", newValue != void 0);
|
|
1355
|
+
} else if (attributeName == "label") {
|
|
1356
|
+
const title = this.findElement("#title");
|
|
1357
|
+
if (title != null) {
|
|
1358
|
+
title.textContent = newValue ?? "Tests";
|
|
1241
1359
|
}
|
|
1242
1360
|
}
|
|
1243
1361
|
}
|
|
1244
|
-
};
|
|
1245
|
-
function generateId() {
|
|
1246
|
-
const rnd = new Uint8Array(20);
|
|
1247
|
-
crypto.getRandomValues(rnd);
|
|
1248
|
-
const b64 = [].slice.apply(rnd).map(function(ch) {
|
|
1249
|
-
return String.fromCharCode(ch);
|
|
1250
|
-
}).join("");
|
|
1251
|
-
const secret = btoa(b64).replace(/\//g, "_").replace(/\+/g, "-").replace(/=/g, "");
|
|
1252
|
-
return secret;
|
|
1253
1362
|
}
|
|
1254
1363
|
if (customElements.get(COMPONENT_TAG_NAME) == null) {
|
|
1255
1364
|
customElements.define(COMPONENT_TAG_NAME, CodeTestsElement);
|
|
1256
1365
|
}
|
|
1366
|
+
function expect(value) {
|
|
1367
|
+
const promise = new TestPromise(async (resolve, _reject) => {
|
|
1368
|
+
if (value instanceof Promise) {
|
|
1369
|
+
const result = await value;
|
|
1370
|
+
resolve(result);
|
|
1371
|
+
return;
|
|
1372
|
+
}
|
|
1373
|
+
resolve(value);
|
|
1374
|
+
});
|
|
1375
|
+
return promise;
|
|
1376
|
+
}
|
|
1377
|
+
async function prompt(host, parentElement, message, options) {
|
|
1378
|
+
return new Promise((resolve, _reject) => {
|
|
1379
|
+
const template = options?.template ?? host.querySelector(".prompt-template") ?? host.findElement("#prompt-template");
|
|
1380
|
+
const promptElement = createElementFromTemplate(template);
|
|
1381
|
+
promptElement.querySelector(".label").textContent = message;
|
|
1382
|
+
const clickHandler = (event) => {
|
|
1383
|
+
const composedPath = event.composedPath();
|
|
1384
|
+
const acceptButton = composedPath.find((item) => item instanceof HTMLButtonElement && item.classList.contains("accept"));
|
|
1385
|
+
if (acceptButton != null) {
|
|
1386
|
+
const result = options?.onAccept?.() ?? true;
|
|
1387
|
+
promptElement.removeEventListener("click", clickHandler);
|
|
1388
|
+
resolve(result);
|
|
1389
|
+
return;
|
|
1390
|
+
}
|
|
1391
|
+
const rejectButton = composedPath.find((item) => item instanceof HTMLButtonElement && item.classList.contains("reject"));
|
|
1392
|
+
if (rejectButton != null) {
|
|
1393
|
+
const result = options?.onReject?.() ?? false;
|
|
1394
|
+
promptElement.removeEventListener("click", clickHandler);
|
|
1395
|
+
resolve(result);
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
};
|
|
1399
|
+
promptElement.addEventListener("click", clickHandler);
|
|
1400
|
+
if (options?.acceptLabel != null) {
|
|
1401
|
+
promptElement.querySelector(".accept").textContent = options.acceptLabel;
|
|
1402
|
+
}
|
|
1403
|
+
if (options?.rejectLabel != null) {
|
|
1404
|
+
promptElement.querySelector(".reject").textContent = options.rejectLabel;
|
|
1405
|
+
}
|
|
1406
|
+
parentElement.append(promptElement);
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
function createElementFromTemplate(target, parent) {
|
|
1410
|
+
const templateNode = target instanceof HTMLTemplateElement ? target : document.querySelector(target);
|
|
1411
|
+
if (templateNode == null) {
|
|
1412
|
+
throw new Error(`Unable to find template element from selector: ${target}`);
|
|
1413
|
+
}
|
|
1414
|
+
const firstChild = templateNode.content.cloneNode(true).firstElementChild;
|
|
1415
|
+
if (firstChild == null) {
|
|
1416
|
+
throw new Error(`Unable to find first child of template element`);
|
|
1417
|
+
}
|
|
1418
|
+
parent?.append(firstChild);
|
|
1419
|
+
return firstChild;
|
|
1420
|
+
}
|
|
1257
1421
|
export {
|
|
1258
|
-
|
|
1259
|
-
|
|
1422
|
+
CodeTestElement,
|
|
1423
|
+
CodeTestEvent,
|
|
1260
1424
|
CodeTestsElement,
|
|
1261
|
-
|
|
1425
|
+
Hook,
|
|
1426
|
+
TestPromise,
|
|
1427
|
+
createElementFromTemplate,
|
|
1262
1428
|
expect,
|
|
1263
1429
|
prompt
|
|
1264
1430
|
};
|