@magnit-ce/code-tests 0.0.1

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.
@@ -0,0 +1,999 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/code-tests.ts
21
+ var code_tests_exports = {};
22
+ __export(code_tests_exports, {
23
+ AFTERALL: () => AFTERALL,
24
+ AFTEREACH: () => AFTEREACH,
25
+ BEFOREALL: () => BEFOREALL,
26
+ BEFOREEACH: () => BEFOREEACH,
27
+ CodeTests: () => CodeTests,
28
+ CodeTestsElement: () => CodeTestsElement,
29
+ expect: () => expect
30
+ });
31
+ module.exports = __toCommonJS(code_tests_exports);
32
+
33
+ // src/code-tests.css?raw
34
+ var code_tests_default = `:host
35
+ {
36
+ /*** gray ***/
37
+ --uchu-light-gray-raw: 95.57% 0.003 286.35;
38
+ --uchu-light-gray: oklch(var(--uchu-light-gray-raw));
39
+
40
+ --uchu-gray-raw: 84.68% 0.002 197.12;
41
+ --uchu-gray: oklch(var(--uchu-gray-raw));
42
+
43
+ --uchu-dark-gray-raw: 63.12% 0.004 219.55;
44
+ --uchu-dark-gray: oklch(var(--uchu-dark-gray-raw));
45
+
46
+ /*** red ***/
47
+ --uchu-light-red-raw: 88.98% 0.052 3.28;
48
+ --uchu-light-red: oklch(var(--uchu-light-red-raw));
49
+
50
+ --uchu-dark-red-raw: 45.8% 0.177 17.7;
51
+ --uchu-dark-red: oklch(var(--uchu-dark-red-raw));
52
+
53
+ /*** purple ***/
54
+ --uchu-light-purple-raw: 89.1% 0.046 305.24;
55
+ --uchu-light-purple: oklch(var(--uchu-light-purple-raw));
56
+
57
+ --uchu-dark-purple-raw: 39.46% 0.164 298.29;
58
+ --uchu-dark-purple: oklch(var(--uchu-dark-purple-raw));
59
+
60
+ /*** blue ***/
61
+ --uchu-light-blue-raw: 89.66% 0.046 260.67;
62
+ --uchu-light-blue: oklch(var(--uchu-light-blue-raw));
63
+
64
+ --uchu-blue-raw: 62.39% 0.181 258.33;
65
+ --uchu-blue: oklch(var(--uchu-blue-raw));
66
+
67
+ --uchu-dark-blue-raw: 43.48% 0.17 260.2;
68
+ --uchu-dark-blue: oklch(var(--uchu-dark-blue-raw));
69
+
70
+ /*** green ***/
71
+ --uchu-light-green-raw: 93.96% 0.05 148.74;
72
+ --uchu-light-green: oklch(var(--uchu-light-green-raw));
73
+
74
+ --uchu-green-raw: 79.33% 0.179 145.62;
75
+ --uchu-green: oklch(var(--uchu-green-raw));
76
+
77
+ --uchu-dark-green-raw: 58.83% 0.158 145.05;
78
+ --uchu-dark-green: oklch(var(--uchu-dark-green-raw));
79
+
80
+ /*** general ***/
81
+ --uchu-yang-raw: 99.4% 0 0;
82
+ --uchu-yang: oklch(var(--uchu-yang-raw));
83
+
84
+ --uchu-yin-raw: 14.38% 0.007 256.88;
85
+ --uchu-yin: oklch(var(--uchu-yin-raw));
86
+
87
+ /*** code-tests vars ***/
88
+
89
+ --spacer: calc(1em - 7px);
90
+ --small-spacer: calc(var(--spacer) / 2);
91
+
92
+ --color-success: var(--uchu-green);
93
+ --color-fail: var(--uchu-red);
94
+ --color-process: var(--uchu-blue);
95
+
96
+ --text-surface: var(--uchu-yin);
97
+ --text-result: var(--uchu-yang); /* --uchu-yang: #fdfdfd; */
98
+ --text-collapse-icon: var(--uchu-dark-gray); /* --uchu-dark-gray: #878a8b; */
99
+ --text-hook-summary: var(--uchu-dark-purple);
100
+ --text-success: var(--uchu-dark-green); /* --uchu-dark-green: #2e943a; */
101
+ --text-fail: var(--uchu-dark-red); /* --uchu-dark-red: #a30d30; */
102
+ --text-process: var(--uchu-dark-blue); /* --uchu-dark-blue: #0949ac; */
103
+ --text-button: var(--uchu-yang); /* --uchu-dark-blue: #0949ac; */
104
+ --text-placeholder: var(--uchu-dark-gray);
105
+
106
+ --surface-0: var(--uchu-light-gray);
107
+ --surface-test: var(--uchu-yang);
108
+ --surface-test-summary: var(--uchu-gray);
109
+ --surface-hook-summary: var(--uchu-light-purple);
110
+ --surface-success: var(--uchu-light-green);
111
+ --surface-fail: var(--uchu-light-red);
112
+ --surface-process: var(--uchu-light-blue);
113
+ --surface-button: var(--uchu-blue); /* --uchu-blue: #3984f2 */
114
+ --surface-button-hover: var(--uchu-light-blue);
115
+ --surface-button-active: var(--uchu-dark-blue);
116
+
117
+ --border-test: solid 1px var(--uchu-dark-gray);
118
+ --border-hook: solid 1px var(--uchu-dark-purple);
119
+ --border-success: solid 1px var(--uchu-dark-green);
120
+ --border-fail: solid 1px var(--uchu-dark-red);
121
+ --border-process: solid 1px var(--uchu-dark-blue);
122
+ --border-button: solid 1px var(--uchu-blue);
123
+
124
+ --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');
125
+
126
+ --font-text: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
127
+
128
+ /*** styles ***/
129
+
130
+ color-scheme: light dark;
131
+ display: grid;
132
+ gap: var(--spacer);
133
+ background-color: var(--surface-0);
134
+ color: var(--text-surface);
135
+ padding: var(--small-spacer);
136
+ font-family: var(--font-text);
137
+ }
138
+ @media (prefers-color-scheme: dark)
139
+ {
140
+ :host
141
+ {
142
+ --text-surface: var(--uchu-yang);
143
+ --text-result: var(--uchu-yang);
144
+
145
+ --surface-0: var(--uchu-yin);
146
+ --surface-test: oklch(25.11% 0.006 258.36);
147
+ --surface-test-summary: oklch(35.02% 0.005 236.66);
148
+ }
149
+ }
150
+
151
+ #header
152
+ {
153
+ display: grid;
154
+ grid-template-columns: 1fr auto;
155
+ align-items: center;
156
+ gap: var(--spacer);
157
+ border-bottom: solid 2px;
158
+ padding: var(--spacer);
159
+ margin-bottom: var(--spacer);
160
+ user-select: none;
161
+ }
162
+
163
+ #title
164
+ {
165
+ font-weight: bold;
166
+ font-size: 16px;
167
+ }
168
+
169
+ .hook
170
+ {
171
+ display: none;
172
+ }
173
+ :host(.has-before-hook) #before-all-details
174
+ ,:host(.has-before-hook) #after-all-details
175
+ {
176
+ display: initial;
177
+ }
178
+
179
+ #tests
180
+ {
181
+ margin: 0;
182
+ padding: 0;
183
+ list-style: none;
184
+ display: grid;
185
+ grid-auto-rows: max-content;
186
+ gap: var(--spacer);
187
+ }
188
+
189
+ summary
190
+ {
191
+ display: grid;
192
+ gap: var(--spacer);
193
+ padding: var(--small-spacer) var(--spacer);
194
+ align-items: center;
195
+ }
196
+ summary::before
197
+ {
198
+ content: '';
199
+ width: 16px;
200
+ height: 16px;
201
+ background: url("data:image/svg+xml,%3Csvg%20viewBox%3D'0%200%2020%2020'%20width%3D'14px'%20height%3D'14px'%20fill%3D'none'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cg%20stroke-width%3D'0'%3E%3C%2Fg%3E%3Cg%20stroke-linecap%3D'round'%20stroke-linejoin%3D'round'%3E%3C%2Fg%3E%3Cg%3E%3Cpath%20d%3D'M8.72798%2015.795L3.72798%207.795C3.10356%206.79593%203.82183%205.5%204.99998%205.5L15%205.5C16.1781%205.5%2016.8964%206.79593%2016.272%207.795L11.272%2015.795C10.6845%2016.735%209.31549%2016.735%208.72798%2015.795Z'%20fill%3D'%23878a8b'%3E%3C%2Fpath%3E%3C%2Fg%3E%3C%2Fsvg%3E");
202
+ transform: rotate(-90deg);
203
+ transition: transform ease-out 200ms;
204
+ }
205
+ [open] > summary::before
206
+ {
207
+ transform: rotate(0);
208
+ /* background: var(--surface-test-summary); */
209
+ }
210
+
211
+ #before-all-summary
212
+ ,#after-all-summary
213
+ {
214
+ background: var(--surface-hook-summary);
215
+ color: var(--text-hook-summary);
216
+ grid-template-columns: auto auto 1fr;
217
+ }
218
+
219
+ .result-icon
220
+ {
221
+ --size: 24px;
222
+ width: var(--size);
223
+ height: var(--size);
224
+
225
+ display: flex;
226
+ align-items: center;
227
+ justify-content: center;
228
+
229
+ border: solid 1px currentColor;
230
+ border-radius: 50%;
231
+ }
232
+ .result-icon::before
233
+ {
234
+ content: '\u22EF';
235
+ }
236
+
237
+ .hook
238
+ {
239
+ border: var(--border-hook);
240
+ }
241
+
242
+ .test
243
+ ,#before-all-details
244
+ ,#after-all-details
245
+ {
246
+ border: var(--border-test);
247
+ border-radius: 2px;
248
+ }
249
+
250
+ .test summary
251
+ {
252
+ background: var(--surface-test-summary);
253
+ grid-template-columns: auto auto 1fr auto;
254
+ }
255
+
256
+ .test.running .result-icon
257
+ ,.hook.running .result-icon
258
+ {
259
+ border: var(--border-process);
260
+ background: var(--surface-process);
261
+ }
262
+ .test.success .result-icon
263
+ ,.hook.success .result-icon
264
+ {
265
+ border: var(--border-success);
266
+ background: var(--surface-success)
267
+ url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" 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>');
268
+ background-repeat: no-repeat;
269
+ background-position: center;
270
+ }
271
+ .test.fail .result-icon
272
+ ,.hook.fail .result-icon
273
+ {
274
+ border: var(--border-fail);
275
+ background: var(--surface-fail)
276
+ var(--info-icon);
277
+ background-repeat: no-repeat;
278
+ background-position: center;
279
+ transform: rotate(175deg);
280
+ }
281
+ .test:is(.success,.fail) .result-icon::before
282
+ ,.hook:is(.success,.fail) .result-icon::before
283
+ {
284
+ display: none;
285
+ }
286
+ .test:is(.running) .result-icon::before
287
+ ,.hook:is(.running) .result-icon::before
288
+ {
289
+ content: '';
290
+ --size: 18px;
291
+ --color: var(--text-process);
292
+ --animation-timing-function: linear;
293
+ --animation-duration: 2s;
294
+ width: var(--size);
295
+ height: var(--size);
296
+ mask-image: radial-gradient(circle at 50% 50%, transparent calc(var(--size) / 3), black calc(var(--size) / 3));
297
+ background-image: conic-gradient(transparent, transparent 135deg, var(--color));
298
+ border-radius: 50%;
299
+ animation: var(--animation-timing-function) var(--animation-duration) infinite spin;
300
+ margin: 2px;
301
+ }
302
+
303
+ .description
304
+ {
305
+ user-select: none;
306
+ }
307
+
308
+ .test .result
309
+ ,.hook .result
310
+ {
311
+ background: var(--surface-test);
312
+ border: var(--border-test);
313
+ border-radius: 2px;
314
+ margin: var(--small-spacer);
315
+ }
316
+
317
+ .test .result:empty::before
318
+ ,.results:empty::before
319
+ {
320
+ content: "[Test has not been run]";
321
+ font-style: italic;
322
+ font-size: 11px;
323
+ color: var(--text-placeholder);
324
+ }
325
+ .results:empty::before
326
+ {
327
+ content: "[Tests have not been run]";
328
+ }
329
+ .before-result:empty
330
+ ,.after-result:empty
331
+ {
332
+ display: none;
333
+ }
334
+
335
+ .test .result
336
+ ,.results
337
+ ,.before-result
338
+ ,.after-result
339
+ {
340
+ padding: var(--small-spacer) var(--spacer);
341
+ }
342
+
343
+ pre
344
+ {
345
+ margin: var(--small-spacer);
346
+ }
347
+
348
+ .run
349
+ {
350
+ width: auto;
351
+ min-width: auto;
352
+ max-width: auto;
353
+ appearance: none;
354
+ display: inline-flex;
355
+ justify-content: center;
356
+ align-items: center;
357
+ padding: 3px 10px 3px 7px;
358
+ font-size: 11px;
359
+ gap: var(--small-spacer);
360
+ border: var(--border-button);
361
+ background: var(--surface-button);
362
+ border-radius: 4px;
363
+ text-shadow: 1px 1px rgb(0 0 0 / .2);
364
+ color: var(--text-button);
365
+ }
366
+ .run:hover
367
+ {
368
+ background: oklch(68.39% 0.181 258.33);
369
+ }
370
+ .run:active
371
+ {
372
+ background: oklch(50.39% 0.181 258.33);
373
+ }
374
+ .run::before
375
+ {
376
+ content: '';
377
+ display: block;
378
+ width: 16px;
379
+ height: 16px;
380
+ transform: rotate(-90deg);
381
+ background:
382
+ url("data:image/svg+xml,%3Csvg%20viewBox%3D'0%200%2020%2020'%20width%3D'16px'%20height%3D'16px'%20fill%3D'none'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cg%20stroke-width%3D'0'%3E%3C%2Fg%3E%3Cg%20stroke-linecap%3D'round'%20stroke-linejoin%3D'round'%3E%3C%2Fg%3E%3Cg%3E%3Cpath%20d%3D'M8.72798%2015.795L3.72798%207.795C3.10356%206.79593%203.82183%205.5%204.99998%205.5L15%205.5C16.1781%205.5%2016.8964%206.79593%2016.272%207.795L11.272%2015.795C10.6845%2016.735%209.31549%2016.735%208.72798%2015.795Z'%20fill%3D'%23fdfdfd'%3E%3C%2Fpath%3E%3C%2Fg%3E%3C%2Fsvg%3E");
383
+ }
384
+
385
+
386
+
387
+ @keyframes spin
388
+ {
389
+ from { transform: rotate(0deg); }
390
+ to { transform: rotate(360deg); }
391
+ }`;
392
+
393
+ // src/code-tests.html?raw
394
+ var code_tests_default2 = '<slot name="header">\n <header id="header">\n <span id="title"><slot name="title"><span id="title-text">Tests</span></slot></span>\n <slot name="play-button">\n <button type="button" class="run" data-all>\n <slot name="play-button-label">\n <span id="play-button-label" class="button-label label icon">Run Tests</span>\n </slot>\n </button>\n </slot>\n <slot name="details"></slot>\n </header>\n</slot>\n<details id="before-all-details" class="hook">\n <summary id="before-all-summary">\n <span id="before-all-result-icon" class="result-icon"></span>\n <span id="before-all-description" class="description">Results from Before All Hook</span>\n </summary>\n <div id="before-all-results" class="results"></div>\n</details>\n<ul id="tests"></ul>\n<details id="after-all-details" class="hook">\n <summary id="after-all-summary">\n <span id="after-all-result-icon" class="result-icon"></span>\n <span id="after-all-description" class="description">Results from After All Hook</span>\n </summary>\n <div id="after-all-results" class="results"></div>\n</details>';
395
+
396
+ // src/api.ts
397
+ var TestPromise = class extends Promise {
398
+ async toBeDefined(valueName) {
399
+ const target = await this;
400
+ if (target == void 0) {
401
+ throw new Error(`${valueName != null ? valueName : "Value"} is undefined`);
402
+ }
403
+ }
404
+ async toBe(value, exact = false) {
405
+ const target = await this;
406
+ const result = exact == true ? target === value : target == value;
407
+ if (result == false) {
408
+ throw new Error(` Value is not equal.
409
+ Expected: ${value}
410
+ Result: ${target}`);
411
+ }
412
+ }
413
+ async toContainText(value) {
414
+ const target = await this;
415
+ }
416
+ async toHaveAttribute(value) {
417
+ const target = await this;
418
+ if (!(target instanceof HTMLElement)) {
419
+ throw new Error("Unable to check for attribute on non-HTMLElement target");
420
+ }
421
+ if (target.getAttribute(value)) {
422
+ throw new Error("Taret does not have attribute");
423
+ }
424
+ }
425
+ };
426
+ var BEFOREALL = Symbol("beforeAll");
427
+ var BEFOREEACH = Symbol("beforeEach");
428
+ var AFTERALL = Symbol("afterAll");
429
+ var AFTEREACH = Symbol("afterEach");
430
+ var CodeTests = class {
431
+ static timeoutMS = 500;
432
+ static #expectInterval;
433
+ static #expectPromise;
434
+ static expect(value) {
435
+ const promise = new TestPromise(async (resolve, reject) => {
436
+ if (value instanceof Promise) {
437
+ const result = await value;
438
+ resolve(result);
439
+ return;
440
+ }
441
+ resolve(value);
442
+ });
443
+ return promise;
444
+ }
445
+ static expectSync(value) {
446
+ const promise = new TestPromise(async (resolve, reject) => {
447
+ if (value instanceof Promise) {
448
+ const result = await value;
449
+ resolve(result);
450
+ return;
451
+ }
452
+ resolve(value);
453
+ });
454
+ return promise;
455
+ }
456
+ static expectBefore(value) {
457
+ const promise = new TestPromise(async (resolve, reject) => {
458
+ if (value instanceof Promise) {
459
+ const result = await value;
460
+ resolve(result);
461
+ return;
462
+ }
463
+ resolve(value);
464
+ });
465
+ return promise;
466
+ }
467
+ };
468
+ function expect(value) {
469
+ return CodeTests.expect(value);
470
+ }
471
+
472
+ // src/code-tests.ts
473
+ var NOTESTDEFINED = Symbol("No Test Defined");
474
+ var COMPONENT_STYLESHEET = new CSSStyleSheet();
475
+ COMPONENT_STYLESHEET.replaceSync(code_tests_default);
476
+ var COMPONENT_TAG_NAME = "code-tests";
477
+ var CodeTestsElement = class extends HTMLElement {
478
+ componentParts = /* @__PURE__ */ new Map();
479
+ getElement(id) {
480
+ if (this.componentParts.get(id) == null) {
481
+ const part = this.findElement(id);
482
+ if (part != null) {
483
+ this.componentParts.set(id, part);
484
+ }
485
+ }
486
+ return this.componentParts.get(id);
487
+ }
488
+ findElement(id) {
489
+ return this.shadowRoot.getElementById(id);
490
+ }
491
+ #hooks = /* @__PURE__ */ new Map();
492
+ #hookIds = {
493
+ [BEFOREALL]: generateId(),
494
+ [BEFOREEACH]: generateId(),
495
+ [AFTEREACH]: generateId(),
496
+ [AFTERALL]: generateId()
497
+ };
498
+ #continueRunningTests = true;
499
+ constructor() {
500
+ super();
501
+ this.attachShadow({ mode: "open" });
502
+ this.shadowRoot.innerHTML = code_tests_default2;
503
+ this.shadowRoot.adoptedStyleSheets.push(COMPONENT_STYLESHEET);
504
+ this.#boundClickHandler = this.#onClick.bind(this);
505
+ }
506
+ connectedCallback() {
507
+ this.addEventListener("click", this.#boundClickHandler);
508
+ const testsPath = this.getAttribute("src") ?? this.getAttribute("test") ?? this.getAttribute("tests") ?? this.getAttribute("run") ?? this.getAttribute("path");
509
+ if (testsPath == null) {
510
+ return;
511
+ }
512
+ this.loadTests(testsPath);
513
+ }
514
+ disconnectedCallback() {
515
+ this.removeEventListener("click", this.#boundClickHandler);
516
+ }
517
+ #boundClickHandler;
518
+ #onClick(event) {
519
+ const runButton = event.composedPath().find((item) => item instanceof HTMLButtonElement && item.classList.contains("run"));
520
+ if (runButton == null) {
521
+ return;
522
+ }
523
+ const parentListItem = runButton.closest("li");
524
+ if (parentListItem == null) {
525
+ const isRunAll = runButton.hasAttribute("data-all");
526
+ if (isRunAll == true) {
527
+ this.runTests();
528
+ }
529
+ return;
530
+ }
531
+ const testId = parentListItem.dataset.testId;
532
+ if (testId == null) {
533
+ return;
534
+ }
535
+ const test = this.#tests.get(testId);
536
+ if (test == null) {
537
+ return;
538
+ }
539
+ this.#runTest(testId, test);
540
+ }
541
+ async loadTests(path) {
542
+ this.classList.remove("has-before-hook");
543
+ this.classList.remove("has-after-hook");
544
+ try {
545
+ const lastSlashIndexInCurrentPath = window.location.href.lastIndexOf("/");
546
+ const currentPathHasExtension = window.location.href.substring(lastSlashIndexInCurrentPath).indexOf(".") != -1;
547
+ const currentPath = currentPathHasExtension == true ? window.location.href.substring(0, lastSlashIndexInCurrentPath + 1) : window.location.href;
548
+ const moduleDirectory = currentPath + path.substring(0, path.lastIndexOf("/") + 1);
549
+ const modulePath = currentPath + path;
550
+ let moduleContent = await (await fetch(modulePath)).text();
551
+ moduleContent = moduleContent.replaceAll(/['"`](((\.\/)|(\.\.\/))+(.*))['"`]/g, `'${moduleDirectory}$1'`);
552
+ const moduleFile = new File([moduleContent], path.substring(path.lastIndexOf("/")), { type: "text/javascript" });
553
+ const moduleURL = URL.createObjectURL(moduleFile);
554
+ const module2 = await import(moduleURL);
555
+ const tests = module2.tests ?? module2.default;
556
+ if (tests == void 0) {
557
+ throw new Error(`Unable to find tests definition in file at path: ${path}`);
558
+ }
559
+ const beforeAll = tests[BEFOREALL];
560
+ if (beforeAll != null) {
561
+ const hookMap = this.#hooks.get(BEFOREALL);
562
+ if (hookMap == null) {
563
+ const map = /* @__PURE__ */ new Map();
564
+ map.set(beforeAll, /* @__PURE__ */ new Set());
565
+ this.#hooks.set(BEFOREALL, map);
566
+ }
567
+ this.classList.add("has-before-hook");
568
+ }
569
+ const beforeEach = tests[BEFOREEACH];
570
+ if (beforeEach != null) {
571
+ const hookMap = this.#hooks.get(BEFOREEACH);
572
+ if (hookMap == null) {
573
+ const map = /* @__PURE__ */ new Map();
574
+ map.set(beforeEach, /* @__PURE__ */ new Set());
575
+ this.#hooks.set(BEFOREEACH, map);
576
+ }
577
+ }
578
+ const afterAll = tests[AFTERALL];
579
+ if (afterAll != null) {
580
+ const hookMap = this.#hooks.get(AFTERALL);
581
+ if (hookMap == null) {
582
+ const map = /* @__PURE__ */ new Map();
583
+ map.set(afterAll, /* @__PURE__ */ new Set());
584
+ this.#hooks.set(AFTERALL, map);
585
+ }
586
+ this.classList.add("has-after-hook");
587
+ }
588
+ const afterEach = tests[AFTEREACH];
589
+ if (afterEach != null) {
590
+ const hookMap = this.#hooks.get(AFTEREACH);
591
+ if (hookMap == null) {
592
+ const map = /* @__PURE__ */ new Map();
593
+ map.set(afterEach, /* @__PURE__ */ new Set());
594
+ this.#hooks.set(AFTEREACH, map);
595
+ }
596
+ }
597
+ for (const [description, test] of Object.entries(tests)) {
598
+ const id = this.#addTest(description, test);
599
+ if (beforeAll != null) {
600
+ const hookMap = this.#hooks.get(BEFOREALL);
601
+ if (hookMap != null) {
602
+ const testIds = hookMap.get(beforeAll);
603
+ if (testIds != null) {
604
+ testIds.add(id);
605
+ }
606
+ }
607
+ }
608
+ if (beforeEach != null) {
609
+ const hookMap = this.#hooks.get(BEFOREEACH);
610
+ if (hookMap != null) {
611
+ const testIds = hookMap.get(beforeEach);
612
+ if (testIds != null) {
613
+ testIds.add(id);
614
+ }
615
+ }
616
+ }
617
+ if (afterAll != null) {
618
+ const hookMap = this.#hooks.get(AFTERALL);
619
+ if (hookMap != null) {
620
+ const testIds = hookMap.get(afterAll);
621
+ if (testIds != null) {
622
+ testIds.add(id);
623
+ }
624
+ }
625
+ }
626
+ if (afterEach != null) {
627
+ const hookMap = this.#hooks.get(AFTEREACH);
628
+ if (hookMap != null) {
629
+ const testIds = hookMap.get(afterEach);
630
+ if (testIds != null) {
631
+ testIds.add(id);
632
+ }
633
+ }
634
+ }
635
+ }
636
+ } catch (error) {
637
+ this.#addProcessError("An error occurred while loading the tasks:", error);
638
+ }
639
+ }
640
+ async runTests() {
641
+ this.#continueRunningTests = true;
642
+ this.classList.add("running");
643
+ this.toggleAttribute("success", false);
644
+ this.#clearTestStatuses();
645
+ const inOrder = this.hasAttribute("in-order");
646
+ const beforeHooks = this.#hooks.get(BEFOREALL);
647
+ if (beforeHooks != null) {
648
+ let hookResult;
649
+ try {
650
+ const hookElement = this.getElement(`before-all-details`);
651
+ hookElement.toggleAttribute("success", false);
652
+ hookElement.classList.add("running");
653
+ hookElement.part.add("running");
654
+ hookElement.classList.remove("success", "fail");
655
+ hookElement.part.remove("success", "fail");
656
+ for (const [hook, ids] of beforeHooks) {
657
+ hookResult = await hook();
658
+ this.#handleHookResult(hookResult, true, "before");
659
+ }
660
+ hookElement.part.remove("running");
661
+ } catch (error) {
662
+ this.#handleHookResult(hookResult, false, "before", error);
663
+ console.error(error);
664
+ this.#continueRunningTests = false;
665
+ return;
666
+ }
667
+ }
668
+ if (inOrder == false) {
669
+ const promises = [];
670
+ for (const [id, test] of this.#tests) {
671
+ promises.push(this.#runTest(id, test));
672
+ }
673
+ await Promise.all(promises);
674
+ } else {
675
+ for (const [id, test] of this.#tests) {
676
+ if (this.#continueRunningTests == false) {
677
+ break;
678
+ }
679
+ await this.#runTest(id, test);
680
+ }
681
+ }
682
+ if (this.#continueRunningTests == false) {
683
+ return;
684
+ }
685
+ const afterHooks = this.#hooks.get(AFTERALL);
686
+ if (afterHooks != null) {
687
+ let hookResult;
688
+ try {
689
+ const hookElement = this.getElement(`after-all-details`);
690
+ hookElement.toggleAttribute("success", false);
691
+ hookElement.classList.add("running");
692
+ hookElement.part.add("running");
693
+ hookElement.classList.remove("success", "fail");
694
+ hookElement.part.remove("success", "fail");
695
+ for (const [hook, ids] of afterHooks) {
696
+ hookResult = await hook();
697
+ this.#handleHookResult(hookResult, true, "after");
698
+ }
699
+ hookElement.part.remove("running");
700
+ } catch (error) {
701
+ this.#handleHookResult(hookResult, false, "after", error);
702
+ console.error(error);
703
+ this.#continueRunningTests = false;
704
+ return;
705
+ }
706
+ }
707
+ const failedTests = this.shadowRoot.querySelectorAll('[success="false"]');
708
+ this.setAttribute("success", failedTests.length == 0 ? "true" : "false");
709
+ this.classList.remove("running");
710
+ }
711
+ #clearTestStatuses() {
712
+ for (const [testId, test] of this.#tests) {
713
+ const testElement = this.getElement("tests").querySelector(`[data-test-id="${testId}"]`);
714
+ if (testElement == null) {
715
+ this.#addProcessError(`Unable to find test element for test: ${testId}`);
716
+ return;
717
+ }
718
+ testElement.toggleAttribute("success", false);
719
+ testElement.classList.remove("success", "fail");
720
+ testElement.part.remove("success", "fail");
721
+ }
722
+ }
723
+ async #runTest(testId, test) {
724
+ const testElement = this.getElement("tests").querySelector(`[data-test-id="${testId}"]`);
725
+ if (testElement == null) {
726
+ this.#addProcessError(`Unable to find test element for test: ${testId}`);
727
+ return;
728
+ }
729
+ testElement.toggleAttribute("success", false);
730
+ testElement.classList.add("running");
731
+ testElement.part.add("running");
732
+ testElement.classList.remove("success", "fail");
733
+ testElement.part.remove("success", "fail");
734
+ const errorMessageElement = testElement.querySelector(".error-message");
735
+ if (errorMessageElement != null) {
736
+ errorMessageElement.textContent = "";
737
+ }
738
+ const detailsElement = testElement.querySelector("details");
739
+ if (detailsElement != null) {
740
+ detailsElement.open = false;
741
+ }
742
+ let beforeResult = NOTESTDEFINED;
743
+ let testResult;
744
+ let afterResult = NOTESTDEFINED;
745
+ let testType;
746
+ try {
747
+ const beforeHooks = this.#hooks.get(BEFOREEACH);
748
+ if (beforeHooks != null) {
749
+ for (const [hook, ids] of beforeHooks) {
750
+ if (ids.has(testId)) {
751
+ beforeResult = await hook();
752
+ break;
753
+ }
754
+ }
755
+ }
756
+ testResult = await test();
757
+ const afterHooks = this.#hooks.get(AFTEREACH);
758
+ if (afterHooks != null) {
759
+ for (const [hook, ids] of afterHooks) {
760
+ if (ids.has(testId)) {
761
+ afterResult = await hook();
762
+ break;
763
+ }
764
+ }
765
+ }
766
+ testType = "before";
767
+ if (beforeResult != NOTESTDEFINED) {
768
+ this.#handleTestResult(testElement, beforeResult, true, void 0, testType);
769
+ }
770
+ testType = void 0;
771
+ this.#handleTestResult(testElement, testResult, true, void 0, testType);
772
+ testType = "after";
773
+ if (afterResult != NOTESTDEFINED) {
774
+ this.#handleTestResult(testElement, afterResult, true, void 0, testType);
775
+ }
776
+ } catch (error) {
777
+ this.#handleTestResult(testElement, testResult, false, error, testType);
778
+ console.error(error);
779
+ this.#continueRunningTests = false;
780
+ } finally {
781
+ testElement?.classList.remove("running");
782
+ }
783
+ }
784
+ #handleTestResult(testElement, result, finishedTest, error, beforeOrAfter) {
785
+ if (result instanceof HTMLElement) {
786
+ this.#setTestResult(testElement, result, finishedTest, beforeOrAfter);
787
+ } else if (result == void 0) {
788
+ const trueMessage = beforeOrAfter == void 0 ? "Passed" : "Hook Ran Successfully";
789
+ const defaultResult = this.#createDefaultResult(finishedTest == true ? `${trueMessage}` : `Failed${error != null ? `:
790
+ ${error.message}` : ""}`, finishedTest, beforeOrAfter);
791
+ this.#setTestResult(testElement, defaultResult, finishedTest, beforeOrAfter);
792
+ } else if (typeof result == "string") {
793
+ const defaultResult = this.#createDefaultResult(`${result}${error == null ? "" : `:
794
+ ${error.message}`}`, finishedTest, beforeOrAfter);
795
+ this.#setTestResult(testElement, defaultResult, finishedTest, beforeOrAfter);
796
+ } else if (typeof result == "object") {
797
+ const objectResult = result;
798
+ if (objectResult.success != void 0 && objectResult.expected != void 0 && objectResult.value != void 0) {
799
+ const trueMessage = beforeOrAfter == void 0 ? "Passed" : "Success";
800
+ const falseMessage = beforeOrAfter == void 0 ? "Failed" : "Fail";
801
+ const defaultResult = this.#createDefaultResult(
802
+ `${objectResult.success == true ? `${trueMessage}:` : `${falseMessage}:`}
803
+ Expected:${objectResult.expected}
804
+ Result:${objectResult.value}`,
805
+ objectResult.success,
806
+ beforeOrAfter
807
+ );
808
+ this.#setTestResult(testElement, defaultResult, finishedTest, beforeOrAfter);
809
+ }
810
+ }
811
+ const detailsElement = testElement.querySelector("details");
812
+ if (detailsElement != null) {
813
+ detailsElement.open = true;
814
+ }
815
+ }
816
+ #handleHookResult(result, finishedTest, beforeOrAfter, error) {
817
+ if (result instanceof HTMLElement) {
818
+ this.#setHookResult(result, finishedTest, beforeOrAfter);
819
+ } else {
820
+ let defaultResult;
821
+ if (result == void 0) {
822
+ defaultResult = this.#createDefaultResult(finishedTest == true ? "Hook Ran Successfully" : `Failed${error != null ? `:
823
+ ${error.message}` : ""}`, finishedTest);
824
+ this.#setHookResult(defaultResult, finishedTest, beforeOrAfter);
825
+ } else if (typeof result == "string") {
826
+ defaultResult = this.#createDefaultResult(`${result}${error == null ? "" : `:
827
+ ${error.message}`}`, finishedTest);
828
+ this.#setHookResult(defaultResult, finishedTest, beforeOrAfter);
829
+ } else if (typeof result == "object") {
830
+ const objectResult = result;
831
+ if (objectResult.success != void 0 && objectResult.expected != void 0 && objectResult.value != void 0) {
832
+ defaultResult = this.#createDefaultResult(
833
+ `${objectResult.success == true ? "Success:" : "Fail:"}
834
+ Expected:${objectResult.expected}
835
+ Result:${objectResult.value}`,
836
+ objectResult.success
837
+ );
838
+ this.#setHookResult(defaultResult, finishedTest, beforeOrAfter);
839
+ }
840
+ }
841
+ }
842
+ const detailsElement = this.getElement(`${beforeOrAfter}-all-details`);
843
+ if (detailsElement != null) {
844
+ detailsElement.open = true;
845
+ }
846
+ }
847
+ static create(properties) {
848
+ const element = document.createElement("code-tests");
849
+ console.log(properties);
850
+ return element;
851
+ }
852
+ #tests = /* @__PURE__ */ new Map();
853
+ #addTest(description, test) {
854
+ const testId = generateId();
855
+ this.#tests.set(testId, test);
856
+ const testElement = this.#createTest(testId, description);
857
+ this.getElement("tests").append(testElement);
858
+ return testId;
859
+ }
860
+ #createTest(testId, description) {
861
+ const testElement = document.createElement("li");
862
+ testElement.dataset.testId = testId;
863
+ testElement.classList.add("test");
864
+ const detailsElement = document.createElement("details");
865
+ detailsElement.classList.add("test-details");
866
+ const summaryElement = document.createElement("summary");
867
+ summaryElement.classList.add("test-summary");
868
+ const resultIcon = document.createElement("div");
869
+ resultIcon.classList.add("result-icon");
870
+ summaryElement.append(resultIcon);
871
+ const descriptionElement = document.createElement("span");
872
+ descriptionElement.classList.add("description", "test-description");
873
+ descriptionElement.textContent = description;
874
+ summaryElement.append(descriptionElement);
875
+ const runButton = document.createElement("button");
876
+ runButton.classList.add("run", "test-run");
877
+ runButton.textContent = "Run Test";
878
+ runButton.title = "Run Test";
879
+ summaryElement.append(runButton);
880
+ const beforeResultElement = document.createElement("div");
881
+ beforeResultElement.classList.add("before-result", "test-before-result");
882
+ const resultElement = document.createElement("div");
883
+ resultElement.classList.add("result", "test-result");
884
+ const afterResultElement = document.createElement("div");
885
+ afterResultElement.classList.add("after-result", "test-after-result");
886
+ detailsElement.append(summaryElement);
887
+ detailsElement.append(beforeResultElement);
888
+ detailsElement.append(resultElement);
889
+ detailsElement.append(afterResultElement);
890
+ testElement.append(detailsElement);
891
+ return testElement;
892
+ }
893
+ #setTestResult(testElement, valueElement, success, beforeOrAfter) {
894
+ testElement.setAttribute("success", success == true ? "true" : "false");
895
+ testElement.classList.toggle("success", success);
896
+ testElement.part.toggle("success", success);
897
+ testElement.classList.toggle("fail", !success);
898
+ testElement.part.toggle("fail", !success);
899
+ const resultElement = testElement.querySelector(`.${beforeOrAfter == void 0 ? "result" : beforeOrAfter == "before" ? "before-result" : "after-result"}`);
900
+ if (resultElement == null) {
901
+ this.#addProcessError(`Unable to find result element`);
902
+ return;
903
+ }
904
+ resultElement.innerHTML = "";
905
+ resultElement.appendChild(valueElement);
906
+ }
907
+ #createDefaultResult(message, success, beforeOrAfter) {
908
+ const codeElement = document.createElement("code");
909
+ const preElement = document.createElement("pre");
910
+ preElement.textContent = message;
911
+ preElement.classList.add(success == true ? "success-message" : "error-message");
912
+ codeElement.appendChild(preElement);
913
+ return codeElement;
914
+ }
915
+ #setHookResult(valueElement, success, beforeOrAfter) {
916
+ const detailsElement = this.getElement(`${beforeOrAfter}-all-details`);
917
+ const resultsElement = this.getElement(`${beforeOrAfter}-all-results`);
918
+ detailsElement.setAttribute("success", success == true ? "true" : "false");
919
+ detailsElement.classList.toggle("success", success);
920
+ detailsElement.part.toggle("success", success);
921
+ detailsElement.classList.toggle("fail", !success);
922
+ detailsElement.part.toggle("fail", !success);
923
+ resultsElement.innerHTML = "";
924
+ resultsElement.appendChild(valueElement);
925
+ }
926
+ #addProcessError(message, error) {
927
+ if (error instanceof Error) {
928
+ message += `
929
+ ${error.message}`;
930
+ console.error(error);
931
+ }
932
+ const errorElement = document.createElement("li");
933
+ const codeElement = document.createElement("code");
934
+ const preElement = document.createElement("pre");
935
+ preElement.textContent = message;
936
+ codeElement.append(preElement);
937
+ errorElement.append(codeElement);
938
+ this.getElement("tests").append(errorElement);
939
+ }
940
+ #updateListType(type) {
941
+ if (type == "ordered") {
942
+ const list = this.shadowRoot.querySelector("ul");
943
+ if (list == null) {
944
+ return;
945
+ }
946
+ const items = this.shadowRoot?.querySelectorAll("li");
947
+ const newList = document.createElement("ol");
948
+ if (items != null) {
949
+ newList.append(...items);
950
+ }
951
+ newList.id = "tests";
952
+ list.replaceWith(newList);
953
+ } else {
954
+ const list = this.shadowRoot.querySelector("ol");
955
+ if (list == null) {
956
+ return;
957
+ }
958
+ const items = this.shadowRoot?.querySelectorAll("li");
959
+ const newList = document.createElement("ul");
960
+ newList.id = "tests";
961
+ if (items != null) {
962
+ newList.append(...items);
963
+ }
964
+ list.replaceWith(newList);
965
+ }
966
+ }
967
+ static observedAttributes = ["in-order"];
968
+ attributeChangedCallback(attributeName, oldValue, newValue) {
969
+ if (attributeName == "in-order") {
970
+ if (newValue == void 0) {
971
+ this.#updateListType("unordered");
972
+ } else {
973
+ this.#updateListType("ordered");
974
+ }
975
+ }
976
+ }
977
+ };
978
+ function generateId() {
979
+ const rnd = new Uint8Array(20);
980
+ crypto.getRandomValues(rnd);
981
+ const b64 = [].slice.apply(rnd).map(function(ch) {
982
+ return String.fromCharCode(ch);
983
+ }).join("");
984
+ const secret = btoa(b64).replace(/\//g, "_").replace(/\+/g, "-").replace(/=/g, "");
985
+ return secret;
986
+ }
987
+ if (customElements.get(COMPONENT_TAG_NAME) == null) {
988
+ customElements.define(COMPONENT_TAG_NAME, CodeTestsElement);
989
+ }
990
+ // Annotate the CommonJS export names for ESM import in node:
991
+ 0 && (module.exports = {
992
+ AFTERALL,
993
+ AFTEREACH,
994
+ BEFOREALL,
995
+ BEFOREEACH,
996
+ CodeTests,
997
+ CodeTestsElement,
998
+ expect
999
+ });