@heyputer/puter.js 2.0.2 → 2.0.3
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/dist/puter.js +4 -0
- package/package.json +6 -2
- package/src/index.js +165 -165
- package/src/safeLoadPuter.cjs +29 -0
- package/APACHE_LICENSE.txt +0 -201
- package/doc/devlog.md +0 -49
- package/index.d.ts +0 -479
- package/src/entry.js +0 -9
- package/test/ai.test.js +0 -214
- package/test/fs.test.js +0 -798
- package/test/index.html +0 -1183
- package/test/kv.test.js +0 -548
- package/test/txt2speech.test.js +0 -178
- package/webpack.config.js +0 -25
package/test/index.html
DELETED
|
@@ -1,1183 +0,0 @@
|
|
|
1
|
-
<html>
|
|
2
|
-
<head>
|
|
3
|
-
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
|
4
|
-
<script id="puter-script"></script>
|
|
5
|
-
<script src="./kv.test.js"></script>
|
|
6
|
-
<script src="./fs.test.js"></script>
|
|
7
|
-
<script src="./ai.test.js"></script>
|
|
8
|
-
<script src="./txt2speech.test.js"></script>
|
|
9
|
-
<style>
|
|
10
|
-
body {
|
|
11
|
-
font-family: Arial, sans-serif;
|
|
12
|
-
}
|
|
13
|
-
nav {
|
|
14
|
-
z-index: 1000;
|
|
15
|
-
display: flex;
|
|
16
|
-
align-items: center;
|
|
17
|
-
position: fixed;
|
|
18
|
-
top: 0;
|
|
19
|
-
width: 100%;
|
|
20
|
-
background: #EEE;
|
|
21
|
-
left: 0;
|
|
22
|
-
padding-left: 10px;
|
|
23
|
-
/* disable text selection */
|
|
24
|
-
user-select: none;
|
|
25
|
-
}
|
|
26
|
-
#tests {
|
|
27
|
-
padding-top: 50px;
|
|
28
|
-
}
|
|
29
|
-
#run-tests {
|
|
30
|
-
margin-top: 20px;
|
|
31
|
-
margin-bottom: 20px;
|
|
32
|
-
background-color: #4c84af;
|
|
33
|
-
border: none;
|
|
34
|
-
color: white;
|
|
35
|
-
padding: 10px 20px;
|
|
36
|
-
text-align: center;
|
|
37
|
-
text-decoration: none;
|
|
38
|
-
display: inline-block;
|
|
39
|
-
font-size: 16px;
|
|
40
|
-
cursor: pointer;
|
|
41
|
-
margin-left: 20px;
|
|
42
|
-
}
|
|
43
|
-
#settings-btn {
|
|
44
|
-
margin-left: auto;
|
|
45
|
-
margin-top: 20px;
|
|
46
|
-
margin-bottom: 20px;
|
|
47
|
-
background-color: #666;
|
|
48
|
-
border: none;
|
|
49
|
-
color: white;
|
|
50
|
-
padding: 10px 20px;
|
|
51
|
-
text-align: center;
|
|
52
|
-
text-decoration: none;
|
|
53
|
-
display: inline-block;
|
|
54
|
-
font-size: 16px;
|
|
55
|
-
cursor: pointer;
|
|
56
|
-
float: right;
|
|
57
|
-
margin-right: 30px;
|
|
58
|
-
}
|
|
59
|
-
#settings-btn:hover {
|
|
60
|
-
background-color: #555;
|
|
61
|
-
}
|
|
62
|
-
#auth-section {
|
|
63
|
-
float: right;
|
|
64
|
-
margin-right: 20px;
|
|
65
|
-
display: flex;
|
|
66
|
-
align-items: center;
|
|
67
|
-
font-size: 14px;
|
|
68
|
-
}
|
|
69
|
-
#login-btn {
|
|
70
|
-
background-color: #4c84af;
|
|
71
|
-
border: none;
|
|
72
|
-
color: white;
|
|
73
|
-
padding: 12px 16px;
|
|
74
|
-
text-align: center;
|
|
75
|
-
text-decoration: none;
|
|
76
|
-
display: inline-block;
|
|
77
|
-
font-size: 14px;
|
|
78
|
-
cursor: pointer;
|
|
79
|
-
}
|
|
80
|
-
#login-btn:hover {
|
|
81
|
-
background-color: #3a6a8a;
|
|
82
|
-
}
|
|
83
|
-
#user-info {
|
|
84
|
-
color: #333;
|
|
85
|
-
}
|
|
86
|
-
#logout-link {
|
|
87
|
-
color: #666;
|
|
88
|
-
text-decoration: underline;
|
|
89
|
-
cursor: pointer;
|
|
90
|
-
margin-left: 5px;
|
|
91
|
-
}
|
|
92
|
-
#logout-link:hover {
|
|
93
|
-
color: #333;
|
|
94
|
-
}
|
|
95
|
-
#unselect-all {
|
|
96
|
-
margin-left: 20px;
|
|
97
|
-
cursor: pointer;
|
|
98
|
-
}
|
|
99
|
-
#select-all {
|
|
100
|
-
margin-left: 20px;
|
|
101
|
-
cursor: pointer;
|
|
102
|
-
}
|
|
103
|
-
.test-container{
|
|
104
|
-
margin-bottom: 10px;
|
|
105
|
-
padding: 10px;
|
|
106
|
-
border-radius: 5px;
|
|
107
|
-
}
|
|
108
|
-
.test-container{
|
|
109
|
-
font-family: monospace;
|
|
110
|
-
}
|
|
111
|
-
.test-checkbox-container{
|
|
112
|
-
display: flex;
|
|
113
|
-
align-items: center;
|
|
114
|
-
}
|
|
115
|
-
.test-container:hover{
|
|
116
|
-
background-color: #f0f0f0;
|
|
117
|
-
}
|
|
118
|
-
.test-container label{
|
|
119
|
-
display: block;
|
|
120
|
-
margin-left: 5px;
|
|
121
|
-
}
|
|
122
|
-
.test-container input{
|
|
123
|
-
float: left;
|
|
124
|
-
}
|
|
125
|
-
.test-name {
|
|
126
|
-
color: #727272;
|
|
127
|
-
}
|
|
128
|
-
.test-description {
|
|
129
|
-
font-size: 12px;
|
|
130
|
-
color: #262626;
|
|
131
|
-
margin-top: 2px;
|
|
132
|
-
}
|
|
133
|
-
.test-run-button {
|
|
134
|
-
margin-left: 10px;
|
|
135
|
-
background-color: #4c84af;
|
|
136
|
-
border: none;
|
|
137
|
-
color: white;
|
|
138
|
-
padding: 5px 10px;
|
|
139
|
-
text-align: center;
|
|
140
|
-
text-decoration: none;
|
|
141
|
-
display: inline-block;
|
|
142
|
-
font-size: 12px;
|
|
143
|
-
cursor: pointer;
|
|
144
|
-
border-radius: 3px;
|
|
145
|
-
opacity: 0;
|
|
146
|
-
transition: opacity 0.2s ease;
|
|
147
|
-
}
|
|
148
|
-
.test-container:hover .test-run-button {
|
|
149
|
-
opacity: 1;
|
|
150
|
-
}
|
|
151
|
-
.test-run-button:hover {
|
|
152
|
-
background-color: #3a6a8a;
|
|
153
|
-
}
|
|
154
|
-
.test-run-button:disabled {
|
|
155
|
-
background-color: #999;
|
|
156
|
-
cursor: not-allowed;
|
|
157
|
-
opacity: 1;
|
|
158
|
-
}
|
|
159
|
-
.test-run-button:disabled:hover {
|
|
160
|
-
background-color: #999;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/* Make h2 headers sticky */
|
|
164
|
-
#tests h2 {
|
|
165
|
-
position: sticky;
|
|
166
|
-
top: 78px; /* Position below the fixed nav */
|
|
167
|
-
background-color: white;
|
|
168
|
-
padding: 20px 0;
|
|
169
|
-
margin: 20px 0 10px 0;
|
|
170
|
-
border-bottom: 2px solid #ddd;
|
|
171
|
-
z-index: 10;
|
|
172
|
-
font-size: 18px;
|
|
173
|
-
font-weight: bold;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/* Adjust sticky headings when progress panel is visible */
|
|
177
|
-
#progress-panel.show ~ #tests h2 {
|
|
178
|
-
top: 158px; /* 78px + 80px to account for progress panel */
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/* Style for h2 checkboxes */
|
|
182
|
-
#tests h2 input[type="checkbox"] {
|
|
183
|
-
margin-right: 18px;
|
|
184
|
-
transform: scale(1.2);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
#tests h2 label {
|
|
188
|
-
cursor: pointer;
|
|
189
|
-
display: flex;
|
|
190
|
-
align-items: center;
|
|
191
|
-
padding-left: 10px;
|
|
192
|
-
font-size: 25px;
|
|
193
|
-
}
|
|
194
|
-
#test-counter {
|
|
195
|
-
font-size: 14px;
|
|
196
|
-
color: #666;
|
|
197
|
-
margin-right: 10px;
|
|
198
|
-
font-size: 20px;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/* Progress panel styles */
|
|
202
|
-
#progress-panel {
|
|
203
|
-
position: fixed;
|
|
204
|
-
top: 78px;
|
|
205
|
-
left: 0;
|
|
206
|
-
right: 0;
|
|
207
|
-
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
208
|
-
color: white;
|
|
209
|
-
padding: 15px 20px;
|
|
210
|
-
z-index: 999;
|
|
211
|
-
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
212
|
-
transform: translateY(-100%);
|
|
213
|
-
transition: transform 0.3s ease-in-out;
|
|
214
|
-
border-bottom: 3px solid #4c84af;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
#progress-panel.show {
|
|
218
|
-
transform: translateY(0);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
#progress-panel.show ~ #tests {
|
|
222
|
-
padding-top: 120px !important;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
.progress-content {
|
|
226
|
-
display: flex;
|
|
227
|
-
justify-content: space-between;
|
|
228
|
-
align-items: center;
|
|
229
|
-
max-width: 1200px;
|
|
230
|
-
margin: 0 auto;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
.progress-left {
|
|
234
|
-
flex: 1;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
.progress-right {
|
|
238
|
-
display: flex;
|
|
239
|
-
gap: 30px;
|
|
240
|
-
align-items: center;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
.progress-stats {
|
|
244
|
-
display: flex;
|
|
245
|
-
gap: 20px;
|
|
246
|
-
margin-top: 8px;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
.progress-stat {
|
|
250
|
-
display: flex;
|
|
251
|
-
flex-direction: column;
|
|
252
|
-
align-items: center;
|
|
253
|
-
min-width: 80px;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
.progress-stat-number {
|
|
257
|
-
font-size: 24px;
|
|
258
|
-
font-weight: bold;
|
|
259
|
-
line-height: 1;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
.progress-stat-label {
|
|
263
|
-
font-size: 11px;
|
|
264
|
-
opacity: 0.9;
|
|
265
|
-
text-transform: uppercase;
|
|
266
|
-
letter-spacing: 0.5px;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
.current-test {
|
|
270
|
-
font-size: 16px;
|
|
271
|
-
font-weight: 500;
|
|
272
|
-
margin-bottom: 5px;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
.progress-bar-container {
|
|
276
|
-
background: rgba(255,255,255,0.2);
|
|
277
|
-
border-radius: 10px;
|
|
278
|
-
height: 8px;
|
|
279
|
-
overflow: hidden;
|
|
280
|
-
margin-top: 10px;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
.progress-bar {
|
|
284
|
-
background: linear-gradient(90deg, #00c851 0%, #00ff88 100%);
|
|
285
|
-
height: 100%;
|
|
286
|
-
border-radius: 10px;
|
|
287
|
-
transition: width 0.3s ease;
|
|
288
|
-
width: 0%;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
.progress-percentage {
|
|
292
|
-
font-size: 28px;
|
|
293
|
-
font-weight: bold;
|
|
294
|
-
color: #fff;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
.stat-passed {
|
|
298
|
-
color: #00ff88;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
.stat-failed {
|
|
302
|
-
color: #ff6b6b;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
.stat-total {
|
|
306
|
-
color: #fff;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
.elapsed-time {
|
|
310
|
-
font-size: 12px;
|
|
311
|
-
opacity: 0.8;
|
|
312
|
-
margin-top: 2px;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
#reset-results:hover {
|
|
316
|
-
color: #333;
|
|
317
|
-
text-decoration: none;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/* Modal styles */
|
|
321
|
-
.modal {
|
|
322
|
-
display: none;
|
|
323
|
-
position: fixed;
|
|
324
|
-
z-index: 2000;
|
|
325
|
-
left: 0;
|
|
326
|
-
top: 0;
|
|
327
|
-
width: 100%;
|
|
328
|
-
height: 100%;
|
|
329
|
-
background-color: rgba(0, 0, 0, 0.5);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
.modal-content {
|
|
333
|
-
background-color: #fefefe;
|
|
334
|
-
margin: 10% auto;
|
|
335
|
-
padding: 20px;
|
|
336
|
-
border: 1px solid #888;
|
|
337
|
-
border-radius: 8px;
|
|
338
|
-
width: 500px;
|
|
339
|
-
max-width: 90%;
|
|
340
|
-
position: relative;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
.close {
|
|
344
|
-
color: #aaa;
|
|
345
|
-
float: right;
|
|
346
|
-
font-size: 28px;
|
|
347
|
-
font-weight: bold;
|
|
348
|
-
cursor: pointer;
|
|
349
|
-
line-height: 1;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
.close:hover,
|
|
353
|
-
.close:focus {
|
|
354
|
-
color: black;
|
|
355
|
-
text-decoration: none;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
.modal h2 {
|
|
359
|
-
margin-top: 0;
|
|
360
|
-
margin-bottom: 20px;
|
|
361
|
-
color: #333;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
.setting-group {
|
|
365
|
-
margin-bottom: 15px;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
.setting-group label {
|
|
369
|
-
display: block;
|
|
370
|
-
margin-bottom: 5px;
|
|
371
|
-
font-weight: bold;
|
|
372
|
-
color: #555;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
.setting-group input {
|
|
376
|
-
width: 100%;
|
|
377
|
-
padding: 8px;
|
|
378
|
-
border: 1px solid #ddd;
|
|
379
|
-
border-radius: 4px;
|
|
380
|
-
font-size: 14px;
|
|
381
|
-
box-sizing: border-box;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
.modal-buttons {
|
|
385
|
-
margin-top: 20px;
|
|
386
|
-
text-align: right;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
.modal-buttons button {
|
|
390
|
-
margin-left: 10px;
|
|
391
|
-
padding: 8px 16px;
|
|
392
|
-
border: none;
|
|
393
|
-
border-radius: 4px;
|
|
394
|
-
cursor: pointer;
|
|
395
|
-
font-size: 14px;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
.btn-cancel {
|
|
399
|
-
background-color: #ccc;
|
|
400
|
-
color: #333;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
.btn-cancel:hover {
|
|
404
|
-
background-color: #bbb;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
.btn-save {
|
|
408
|
-
background-color: #4c84af;
|
|
409
|
-
color: white;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
.btn-save:hover {
|
|
413
|
-
background-color: #3a6a8a;
|
|
414
|
-
}
|
|
415
|
-
</style>
|
|
416
|
-
<script>
|
|
417
|
-
// Settings management
|
|
418
|
-
const DEFAULT_SETTINGS = {
|
|
419
|
-
puterJsUrl: 'https://js.puter.com/v2/',
|
|
420
|
-
apiOrigin: 'https://api.puter.com'
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
let currentSettings = { ...DEFAULT_SETTINGS };
|
|
424
|
-
|
|
425
|
-
// Authentication functionality
|
|
426
|
-
async function updateAuthUI() {
|
|
427
|
-
try {
|
|
428
|
-
if (typeof puter === 'undefined' || !puter.auth) {
|
|
429
|
-
// Puter not loaded yet, show login button
|
|
430
|
-
$('#login-btn').show();
|
|
431
|
-
$('#user-info').hide();
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
const isSignedIn = await puter.auth.isSignedIn();
|
|
436
|
-
|
|
437
|
-
if (isSignedIn) {
|
|
438
|
-
let user = await puter.auth.getUser();
|
|
439
|
-
// User is signed in, show username and logout option
|
|
440
|
-
$('#login-btn').hide();
|
|
441
|
-
$('#user-info').show();
|
|
442
|
-
|
|
443
|
-
// Get user info - for now we'll use a placeholder
|
|
444
|
-
// In a real app, you might want to get the actual username from puter
|
|
445
|
-
$('#username').text(user.username); // You may need to get actual username from puter API
|
|
446
|
-
} else {
|
|
447
|
-
// User is not signed in, show login button
|
|
448
|
-
$('#login-btn').show();
|
|
449
|
-
$('#user-info').hide();
|
|
450
|
-
}
|
|
451
|
-
} catch (error) {
|
|
452
|
-
console.error('Error checking auth state:', error);
|
|
453
|
-
// If there's an error, default to showing login button
|
|
454
|
-
$('#login-btn').show();
|
|
455
|
-
$('#user-info').hide();
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// Load settings from localStorage or use defaults
|
|
460
|
-
function loadSettings() {
|
|
461
|
-
const saved = localStorage.getItem('puter-test-settings');
|
|
462
|
-
if (saved) {
|
|
463
|
-
try {
|
|
464
|
-
currentSettings = { ...DEFAULT_SETTINGS, ...JSON.parse(saved) };
|
|
465
|
-
} catch (e) {
|
|
466
|
-
console.warn('Failed to parse saved settings, using defaults');
|
|
467
|
-
currentSettings = { ...DEFAULT_SETTINGS };
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
// Save settings to localStorage
|
|
473
|
-
function saveSettings() {
|
|
474
|
-
localStorage.setItem('puter-test-settings', JSON.stringify(currentSettings));
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
// Load Puter.js script dynamically
|
|
478
|
-
function loadPuterScript() {
|
|
479
|
-
return new Promise((resolve, reject) => {
|
|
480
|
-
const script = document.getElementById('puter-script');
|
|
481
|
-
|
|
482
|
-
// Remove existing script if any
|
|
483
|
-
if (script.src) {
|
|
484
|
-
script.remove();
|
|
485
|
-
const newScript = document.createElement('script');
|
|
486
|
-
newScript.id = 'puter-script';
|
|
487
|
-
document.head.insertBefore(newScript, script.nextSibling);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
const puterScript = document.getElementById('puter-script');
|
|
491
|
-
puterScript.onload = resolve;
|
|
492
|
-
puterScript.onerror = reject;
|
|
493
|
-
puterScript.src = currentSettings.puterJsUrl;
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
// Initialize Puter with settings
|
|
498
|
-
async function initializePuter() {
|
|
499
|
-
try {
|
|
500
|
-
await loadPuterScript();
|
|
501
|
-
|
|
502
|
-
// Wait a bit for the script to initialize
|
|
503
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
504
|
-
|
|
505
|
-
// Set API origin if puter object exists
|
|
506
|
-
if (typeof puter !== 'undefined' && puter.setAPIOrigin) {
|
|
507
|
-
puter.setAPIOrigin(currentSettings.apiOrigin);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// Update auth UI after puter is loaded
|
|
511
|
-
await updateAuthUI();
|
|
512
|
-
} catch (error) {
|
|
513
|
-
console.error('Failed to load Puter.js:', error);
|
|
514
|
-
alert('Failed to load Puter.js. Please check the URL in settings.');
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
// Initialize on page load
|
|
519
|
-
document.addEventListener("DOMContentLoaded", async () => {
|
|
520
|
-
loadSettings();
|
|
521
|
-
await initializePuter();
|
|
522
|
-
|
|
523
|
-
// Progress tracking variables
|
|
524
|
-
let testProgress = {
|
|
525
|
-
total: 0,
|
|
526
|
-
completed: 0,
|
|
527
|
-
passed: 0,
|
|
528
|
-
failed: 0,
|
|
529
|
-
startTime: null,
|
|
530
|
-
currentTest: '',
|
|
531
|
-
timerInterval: null
|
|
532
|
-
};
|
|
533
|
-
|
|
534
|
-
// Progress panel functions
|
|
535
|
-
function showProgressPanel() {
|
|
536
|
-
$('#progress-panel').addClass('show');
|
|
537
|
-
$('#run-tests').prop('disabled', true).text('Running Tests...');
|
|
538
|
-
startProgressTimer();
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
function hideProgressPanel() {
|
|
542
|
-
$('#progress-panel').removeClass('show');
|
|
543
|
-
$('#run-tests').prop('disabled', false).text('Run Tests');
|
|
544
|
-
stopProgressTimer();
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
function updateProgressPanel() {
|
|
548
|
-
const { total, completed, passed, failed, currentTest } = testProgress;
|
|
549
|
-
const percentage = total > 0 ? Math.round((completed / total) * 100) : 0;
|
|
550
|
-
|
|
551
|
-
$('#current-test').text(currentTest || 'Preparing tests...');
|
|
552
|
-
$('#progress-bar').css('width', percentage + '%');
|
|
553
|
-
$('#progress-percentage').text(percentage + '%');
|
|
554
|
-
$('#passed-count').text(passed);
|
|
555
|
-
$('#failed-count').text(failed);
|
|
556
|
-
$('#total-count').text(total);
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
function startProgressTimer() {
|
|
560
|
-
testProgress.startTime = Date.now();
|
|
561
|
-
testProgress.timerInterval = setInterval(() => {
|
|
562
|
-
const elapsed = Math.floor((Date.now() - testProgress.startTime) / 1000);
|
|
563
|
-
$('#elapsed-time').text(`Elapsed: ${elapsed}s`);
|
|
564
|
-
}, 1000);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
function stopProgressTimer() {
|
|
568
|
-
if (testProgress.timerInterval) {
|
|
569
|
-
clearInterval(testProgress.timerInterval);
|
|
570
|
-
testProgress.timerInterval = null;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
function resetProgress() {
|
|
575
|
-
testProgress.total = 0;
|
|
576
|
-
testProgress.completed = 0;
|
|
577
|
-
testProgress.passed = 0;
|
|
578
|
-
testProgress.failed = 0;
|
|
579
|
-
testProgress.currentTest = '';
|
|
580
|
-
testProgress.startTime = null;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
function getSelectedTestsCount() {
|
|
584
|
-
return $('.test-checkbox:checked').length;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// Small delay to make progress visible
|
|
588
|
-
function delay(ms) {
|
|
589
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
window.pass = function(msg) {
|
|
593
|
-
// $('#tests').append(`<p style="color:green;">${msg}</p>`);
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
window.fail = function(msg, error) {
|
|
597
|
-
// Include the full error information in the thrown error
|
|
598
|
-
let fullMessage = msg;
|
|
599
|
-
if (error) {
|
|
600
|
-
if (typeof error === 'string') {
|
|
601
|
-
fullMessage += ' ' + error;
|
|
602
|
-
} else if (error.message) {
|
|
603
|
-
fullMessage += ' ' + error.message;
|
|
604
|
-
} else {
|
|
605
|
-
fullMessage += ' ' + JSON.stringify(error);
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
const err = new Error(fullMessage);
|
|
609
|
-
// Attach the original error for detailed display
|
|
610
|
-
err.originalError = error;
|
|
611
|
-
throw err;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
// Function to get test name and description
|
|
615
|
-
function getTestInfo(test) {
|
|
616
|
-
if (typeof test === 'function') {
|
|
617
|
-
return {
|
|
618
|
-
name: test.name,
|
|
619
|
-
description: test.description || 'No description provided'
|
|
620
|
-
};
|
|
621
|
-
} else if (typeof test === 'object' && test.name && test.test) {
|
|
622
|
-
return {
|
|
623
|
-
name: test.name,
|
|
624
|
-
description: test.description || 'No description provided'
|
|
625
|
-
};
|
|
626
|
-
}
|
|
627
|
-
return {
|
|
628
|
-
name: 'Unknown Test',
|
|
629
|
-
description: 'No description provided'
|
|
630
|
-
};
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
// Function to execute a test
|
|
634
|
-
async function executeTest(test) {
|
|
635
|
-
if (typeof test === 'function') {
|
|
636
|
-
return await test();
|
|
637
|
-
} else if (typeof test === 'object' && test.test) {
|
|
638
|
-
return await test.test();
|
|
639
|
-
}
|
|
640
|
-
throw new Error('Invalid test format');
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
// print the test name with checkbox for each test
|
|
644
|
-
$('#tests').append('<h2><label><input type="checkbox" id="fsTests-group"> FileSystem</label></h2>');
|
|
645
|
-
for (let i = 0; i < fsTests.length; i++) {
|
|
646
|
-
const testInfo = getTestInfo(fsTests[i]);
|
|
647
|
-
$('#tests').append(`<div class="test-container" id="fsTests-container-${i}">
|
|
648
|
-
<div class="test-checkbox-container">
|
|
649
|
-
<input type="checkbox" class="test-checkbox fsTests-checkbox" id="fsTests${i}">
|
|
650
|
-
<label for="fsTests${i}">
|
|
651
|
-
<div class="test-name">${testInfo.name}</div>
|
|
652
|
-
<div class="test-description">${testInfo.description}</div>
|
|
653
|
-
</label><br>
|
|
654
|
-
<button class="test-run-button" onclick="runSingleTest('fs', ${i})">Run Test</button>
|
|
655
|
-
</div>
|
|
656
|
-
</div>`);
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
$('#tests').append('<h2><label><input type="checkbox" id="kvTests-group"> Key Value Store</label></h2>');
|
|
660
|
-
for (let i = 0; i < kvTests.length; i++) {
|
|
661
|
-
const testInfo = getTestInfo(kvTests[i]);
|
|
662
|
-
$('#tests').append(`<div class="test-container" id="kvTests-container-${i}">
|
|
663
|
-
<div class="test-checkbox-container">
|
|
664
|
-
<input type="checkbox" class="test-checkbox kvTests-checkbox" id="kvTests${i}">
|
|
665
|
-
<label for="kvTests${i}">
|
|
666
|
-
<div class="test-name">${testInfo.name}</div>
|
|
667
|
-
<div class="test-description">${testInfo.description}</div>
|
|
668
|
-
</label><br>
|
|
669
|
-
<button class="test-run-button" onclick="runSingleTest('kv', ${i})">Run Test</button>
|
|
670
|
-
</div>
|
|
671
|
-
</div>`);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
$('#tests').append('<h2><label><input type="checkbox" id="aiTests-group"> AI</label></h2>');
|
|
675
|
-
for (let i = 0; i < aiTests.length; i++) {
|
|
676
|
-
const testInfo = getTestInfo(aiTests[i]);
|
|
677
|
-
$('#tests').append(`<div class="test-container" id="aiTests-container-${i}">
|
|
678
|
-
<div class="test-checkbox-container">
|
|
679
|
-
<input type="checkbox" class="test-checkbox aiTests-checkbox" id="aiTests${i}">
|
|
680
|
-
<label for="aiTests${i}">
|
|
681
|
-
<div class="test-name">${testInfo.name}</div>
|
|
682
|
-
<div class="test-description">${testInfo.description}</div>
|
|
683
|
-
</label><br>
|
|
684
|
-
<button class="test-run-button" onclick="runSingleTest('ai', ${i})">Run Test</button>
|
|
685
|
-
</div>
|
|
686
|
-
</div>`);
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
$('#tests').append('<h2><label><input type="checkbox" id="txt2speechTests-group"> Text-to-Speech</label></h2>');
|
|
690
|
-
for (let i = 0; i < txt2speechTests.length; i++) {
|
|
691
|
-
const testInfo = getTestInfo(txt2speechTests[i]);
|
|
692
|
-
$('#tests').append(`<div class="test-container" id="txt2speechTests-container-${i}">
|
|
693
|
-
<div class="test-checkbox-container">
|
|
694
|
-
<input type="checkbox" class="test-checkbox txt2speechTests-checkbox" id="txt2speechTests${i}">
|
|
695
|
-
<label for="txt2speechTests${i}">
|
|
696
|
-
<div class="test-name">${testInfo.name}</div>
|
|
697
|
-
<div class="test-description">${testInfo.description}</div>
|
|
698
|
-
</label><br>
|
|
699
|
-
<button class="test-run-button" onclick="runSingleTest('txt2speech', ${i})">Run Test</button>
|
|
700
|
-
</div>
|
|
701
|
-
</div>`);
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// Add event listeners for group checkboxes
|
|
705
|
-
$('#fsTests-group').change(function() {
|
|
706
|
-
const isChecked = $(this).prop('checked');
|
|
707
|
-
$('.fsTests-checkbox').prop('checked', isChecked);
|
|
708
|
-
});
|
|
709
|
-
|
|
710
|
-
$('#kvTests-group').change(function() {
|
|
711
|
-
const isChecked = $(this).prop('checked');
|
|
712
|
-
$('.kvTests-checkbox').prop('checked', isChecked);
|
|
713
|
-
});
|
|
714
|
-
|
|
715
|
-
$('#aiTests-group').change(function() {
|
|
716
|
-
const isChecked = $(this).prop('checked');
|
|
717
|
-
$('.aiTests-checkbox').prop('checked', isChecked);
|
|
718
|
-
});
|
|
719
|
-
|
|
720
|
-
$('#txt2speechTests-group').change(function() {
|
|
721
|
-
const isChecked = $(this).prop('checked');
|
|
722
|
-
$('.txt2speechTests-checkbox').prop('checked', isChecked);
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
// Add event listeners for individual checkboxes to update group checkbox state
|
|
726
|
-
$(document).on('change', '.fsTests-checkbox', function() {
|
|
727
|
-
const totalFsTests = $('.fsTests-checkbox').length;
|
|
728
|
-
const checkedFsTests = $('.fsTests-checkbox:checked').length;
|
|
729
|
-
|
|
730
|
-
if (checkedFsTests === 0) {
|
|
731
|
-
$('#fsTests-group').prop('checked', false).prop('indeterminate', false);
|
|
732
|
-
} else if (checkedFsTests === totalFsTests) {
|
|
733
|
-
$('#fsTests-group').prop('checked', true).prop('indeterminate', false);
|
|
734
|
-
} else {
|
|
735
|
-
$('#fsTests-group').prop('checked', false).prop('indeterminate', true);
|
|
736
|
-
}
|
|
737
|
-
});
|
|
738
|
-
|
|
739
|
-
$(document).on('change', '.kvTests-checkbox', function() {
|
|
740
|
-
const totalKvTests = $('.kvTests-checkbox').length;
|
|
741
|
-
const checkedKvTests = $('.kvTests-checkbox:checked').length;
|
|
742
|
-
|
|
743
|
-
if (checkedKvTests === 0) {
|
|
744
|
-
$('#kvTests-group').prop('checked', false).prop('indeterminate', false);
|
|
745
|
-
} else if (checkedKvTests === totalKvTests) {
|
|
746
|
-
$('#kvTests-group').prop('checked', true).prop('indeterminate', false);
|
|
747
|
-
} else {
|
|
748
|
-
$('#kvTests-group').prop('checked', false).prop('indeterminate', true);
|
|
749
|
-
}
|
|
750
|
-
});
|
|
751
|
-
|
|
752
|
-
$(document).on('change', '.aiTests-checkbox', function() {
|
|
753
|
-
const totalAiTests = $('.aiTests-checkbox').length;
|
|
754
|
-
const checkedAiTests = $('.aiTests-checkbox:checked').length;
|
|
755
|
-
|
|
756
|
-
if (checkedAiTests === 0) {
|
|
757
|
-
$('#aiTests-group').prop('checked', false).prop('indeterminate', false);
|
|
758
|
-
} else if (checkedAiTests === totalAiTests) {
|
|
759
|
-
$('#aiTests-group').prop('checked', true).prop('indeterminate', false);
|
|
760
|
-
} else {
|
|
761
|
-
$('#aiTests-group').prop('checked', false).prop('indeterminate', true);
|
|
762
|
-
}
|
|
763
|
-
});
|
|
764
|
-
|
|
765
|
-
$(document).on('change', '.txt2speechTests-checkbox', function() {
|
|
766
|
-
const totalTxt2speechTests = $('.txt2speechTests-checkbox').length;
|
|
767
|
-
const checkedTxt2speechTests = $('.txt2speechTests-checkbox:checked').length;
|
|
768
|
-
|
|
769
|
-
if (checkedTxt2speechTests === 0) {
|
|
770
|
-
$('#txt2speechTests-group').prop('checked', false).prop('indeterminate', false);
|
|
771
|
-
} else if (checkedTxt2speechTests === totalTxt2speechTests) {
|
|
772
|
-
$('#txt2speechTests-group').prop('checked', true).prop('indeterminate', false);
|
|
773
|
-
} else {
|
|
774
|
-
$('#txt2speechTests-group').prop('checked', false).prop('indeterminate', true);
|
|
775
|
-
}
|
|
776
|
-
});
|
|
777
|
-
|
|
778
|
-
window.assert = function(condition, message) {
|
|
779
|
-
if (!condition) {
|
|
780
|
-
throw new Error(message || "Assertion failed");
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
async function runSingleTest(testType, index) {
|
|
785
|
-
const testSuites = {
|
|
786
|
-
'fs': fsTests,
|
|
787
|
-
'kv': kvTests,
|
|
788
|
-
'ai': aiTests,
|
|
789
|
-
'txt2speech': txt2speechTests
|
|
790
|
-
};
|
|
791
|
-
|
|
792
|
-
const tests = testSuites[testType];
|
|
793
|
-
const containerId = `${testType}Tests-container-${index}`;
|
|
794
|
-
const buttonSelector = `#${containerId} .test-run-button`;
|
|
795
|
-
|
|
796
|
-
// Disable the button and show it while running
|
|
797
|
-
$(buttonSelector).prop('disabled', true).text('Running...');
|
|
798
|
-
|
|
799
|
-
// Clear previous results
|
|
800
|
-
$(`#${containerId}`).css('background-color', '');
|
|
801
|
-
$(`#${containerId} pre`).remove();
|
|
802
|
-
|
|
803
|
-
try {
|
|
804
|
-
await executeTest(tests[index]);
|
|
805
|
-
// make this test's container green
|
|
806
|
-
$(`#${containerId}`).css('background-color', '#85e085');
|
|
807
|
-
} catch (e) {
|
|
808
|
-
const testInfo = getTestInfo(tests[index]);
|
|
809
|
-
console.error(`${testType.toUpperCase()} Test failed:`, testInfo.name, e);
|
|
810
|
-
// make this test's container red
|
|
811
|
-
$(`#${containerId}`).css('background-color', '#ffbfbf');
|
|
812
|
-
// message - show full error information including JSON details
|
|
813
|
-
let errorMessage = e.message || e.toString();
|
|
814
|
-
if (e.originalError) {
|
|
815
|
-
errorMessage += '\n\nOriginal Error:\n' + JSON.stringify(e.originalError, null, 2);
|
|
816
|
-
}
|
|
817
|
-
$(`#${containerId}`).append(`<pre style="color:#c00000; white-space: pre-wrap; font-size: 12px; margin: 5px 0; padding: 10px; background-color: #f8f8f8; border-radius: 3px;">${errorMessage}</pre>`);
|
|
818
|
-
} finally {
|
|
819
|
-
// Re-enable the button
|
|
820
|
-
$(buttonSelector).prop('disabled', false).text('Run Test');
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
window.runSingleTest = runSingleTest;
|
|
825
|
-
|
|
826
|
-
async function runTests() {
|
|
827
|
-
// Reset and initialize progress tracking
|
|
828
|
-
resetProgress();
|
|
829
|
-
testProgress.total = getSelectedTestsCount();
|
|
830
|
-
|
|
831
|
-
// Show progress panel
|
|
832
|
-
showProgressPanel();
|
|
833
|
-
updateProgressPanel();
|
|
834
|
-
|
|
835
|
-
// Clear previous test results
|
|
836
|
-
$('.test-container').css('background-color', '');
|
|
837
|
-
$('.test-container pre').remove();
|
|
838
|
-
|
|
839
|
-
// go through fsTests and run each test
|
|
840
|
-
for (let i = 0; i < fsTests.length; i++) {
|
|
841
|
-
if (document.getElementById(`fsTests${i}`).checked) {
|
|
842
|
-
const testInfo = getTestInfo(fsTests[i]);
|
|
843
|
-
testProgress.currentTest = `FileSystem: ${testInfo.name}`;
|
|
844
|
-
updateProgressPanel();
|
|
845
|
-
|
|
846
|
-
try{
|
|
847
|
-
await executeTest(fsTests[i]);
|
|
848
|
-
// make this test's container green
|
|
849
|
-
$(`#fsTests-container-${i}`).css('background-color', '#85e085');
|
|
850
|
-
testProgress.passed++;
|
|
851
|
-
} catch (e) {
|
|
852
|
-
console.error('FS Test failed:', testInfo.name, e);
|
|
853
|
-
// make this test's container red
|
|
854
|
-
$(`#fsTests-container-${i}`).css('background-color', '#ffbfbf');
|
|
855
|
-
// message - show full error information including JSON details
|
|
856
|
-
let errorMessage = e.message || e.toString();
|
|
857
|
-
if (e.originalError) {
|
|
858
|
-
errorMessage += '\n\nOriginal Error:\n' + JSON.stringify(e.originalError, null, 2);
|
|
859
|
-
}
|
|
860
|
-
$(`#fsTests-container-${i}`).append(`<pre style="color:#c00000; white-space: pre-wrap; font-size: 12px; margin: 5px 0; padding: 10px; background-color: #f8f8f8; border-radius: 3px;">${errorMessage}</pre>`);
|
|
861
|
-
testProgress.failed++;
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
testProgress.completed++;
|
|
865
|
-
updateProgressPanel();
|
|
866
|
-
|
|
867
|
-
// Small delay to make progress visible
|
|
868
|
-
await delay(100);
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
for (let i = 0; i < kvTests.length; i++) {
|
|
873
|
-
if (document.getElementById(`kvTests${i}`).checked) {
|
|
874
|
-
const testInfo = getTestInfo(kvTests[i]);
|
|
875
|
-
testProgress.currentTest = `Key-Value Store: ${testInfo.name}`;
|
|
876
|
-
updateProgressPanel();
|
|
877
|
-
|
|
878
|
-
try{
|
|
879
|
-
await executeTest(kvTests[i]);
|
|
880
|
-
// make this test's container green
|
|
881
|
-
$(`#kvTests-container-${i}`).css('background-color', '#85e085');
|
|
882
|
-
testProgress.passed++;
|
|
883
|
-
} catch (e) {
|
|
884
|
-
console.error('KV Test failed:', testInfo.name, e);
|
|
885
|
-
// make this test's container red
|
|
886
|
-
$(`#kvTests-container-${i}`).css('background-color', '#ff8484');
|
|
887
|
-
// message - show full error information including JSON details
|
|
888
|
-
let errorMessage = e.message || e.toString();
|
|
889
|
-
if (e.originalError) {
|
|
890
|
-
errorMessage += '\n\nOriginal Error:\n' + JSON.stringify(e.originalError, null, 2);
|
|
891
|
-
}
|
|
892
|
-
$(`#kvTests-container-${i}`).append(`<pre style="color:red; white-space: pre-wrap; font-size: 12px; margin: 5px 0; padding: 10px; background-color: #f8f8f8; border-radius: 3px;">${errorMessage}</pre>`);
|
|
893
|
-
testProgress.failed++;
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
testProgress.completed++;
|
|
897
|
-
updateProgressPanel();
|
|
898
|
-
|
|
899
|
-
// Small delay to make progress visible
|
|
900
|
-
await delay(100);
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
for (let i = 0; i < aiTests.length; i++) {
|
|
905
|
-
if (document.getElementById(`aiTests${i}`).checked) {
|
|
906
|
-
const testInfo = getTestInfo(aiTests[i]);
|
|
907
|
-
testProgress.currentTest = `AI: ${testInfo.name}`;
|
|
908
|
-
updateProgressPanel();
|
|
909
|
-
|
|
910
|
-
try{
|
|
911
|
-
await executeTest(aiTests[i]);
|
|
912
|
-
// make this test's container green
|
|
913
|
-
$(`#aiTests-container-${i}`).css('background-color', '#85e085');
|
|
914
|
-
testProgress.passed++;
|
|
915
|
-
} catch (e) {
|
|
916
|
-
console.error('AI Test failed:', testInfo.name, e);
|
|
917
|
-
// make this test's container red
|
|
918
|
-
$(`#aiTests-container-${i}`).css('background-color', '#ff8484');
|
|
919
|
-
// message - show full error information including JSON details
|
|
920
|
-
let errorMessage = e.message || e.toString();
|
|
921
|
-
if (e.originalError) {
|
|
922
|
-
errorMessage += '\n\nOriginal Error:\n' + JSON.stringify(e.originalError, null, 2);
|
|
923
|
-
}
|
|
924
|
-
$(`#aiTests-container-${i}`).append(`<pre style="color:red; white-space: pre-wrap; font-size: 12px; margin: 5px 0; padding: 10px; background-color: #f8f8f8; border-radius: 3px;">${errorMessage}</pre>`);
|
|
925
|
-
testProgress.failed++;
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
testProgress.completed++;
|
|
929
|
-
updateProgressPanel();
|
|
930
|
-
|
|
931
|
-
// Small delay to make progress visible
|
|
932
|
-
await delay(100);
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
for (let i = 0; i < txt2speechTests.length; i++) {
|
|
937
|
-
if (document.getElementById(`txt2speechTests${i}`).checked) {
|
|
938
|
-
const testInfo = getTestInfo(txt2speechTests[i]);
|
|
939
|
-
testProgress.currentTest = `Text-to-Speech: ${testInfo.name}`;
|
|
940
|
-
updateProgressPanel();
|
|
941
|
-
|
|
942
|
-
try{
|
|
943
|
-
await executeTest(txt2speechTests[i]);
|
|
944
|
-
// make this test's container green
|
|
945
|
-
$(`#txt2speechTests-container-${i}`).css('background-color', '#85e085');
|
|
946
|
-
testProgress.passed++;
|
|
947
|
-
} catch (e) {
|
|
948
|
-
console.error('Txt2Speech Test failed:', testInfo.name, e);
|
|
949
|
-
// make this test's container red
|
|
950
|
-
$(`#txt2speechTests-container-${i}`).css('background-color', '#ff8484');
|
|
951
|
-
// message - show full error information including JSON details
|
|
952
|
-
let errorMessage = e.message || e.toString();
|
|
953
|
-
if (e.originalError) {
|
|
954
|
-
errorMessage += '\n\nOriginal Error:\n' + JSON.stringify(e.originalError, null, 2);
|
|
955
|
-
}
|
|
956
|
-
$(`#txt2speechTests-container-${i}`).append(`<pre style="color:red; white-space: pre-wrap; font-size: 12px; margin: 5px 0; padding: 10px; background-color: #f8f8f8; border-radius: 3px;">${errorMessage}</pre>`);
|
|
957
|
-
testProgress.failed++;
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
testProgress.completed++;
|
|
961
|
-
updateProgressPanel();
|
|
962
|
-
|
|
963
|
-
// Small delay to make progress visible
|
|
964
|
-
await delay(100);
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
// Show completion message
|
|
969
|
-
testProgress.currentTest = `Complete! ${testProgress.passed} passed, ${testProgress.failed} failed`;
|
|
970
|
-
updateProgressPanel();
|
|
971
|
-
|
|
972
|
-
// Stop the elapsed timer but keep panel visible
|
|
973
|
-
stopProgressTimer();
|
|
974
|
-
|
|
975
|
-
// Re-enable the run tests button
|
|
976
|
-
$('#run-tests').prop('disabled', false).text('Run Tests');
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
$('#run-tests').click(() => {
|
|
980
|
-
runTests();
|
|
981
|
-
});
|
|
982
|
-
|
|
983
|
-
// Reset results functionality
|
|
984
|
-
$('#reset-results').click(() => {
|
|
985
|
-
// Clear all test container background colors
|
|
986
|
-
$('.test-container').css('background-color', '');
|
|
987
|
-
// Remove all error message pre elements
|
|
988
|
-
$('.test-container pre').remove();
|
|
989
|
-
// Hide progress panel if it's showing
|
|
990
|
-
hideProgressPanel();
|
|
991
|
-
// Reset progress tracking
|
|
992
|
-
resetProgress();
|
|
993
|
-
});
|
|
994
|
-
|
|
995
|
-
// Master checkbox functionality
|
|
996
|
-
$('#master-checkbox').change(function() {
|
|
997
|
-
const isChecked = $(this).prop('checked');
|
|
998
|
-
$('.test-checkbox').prop('checked', isChecked);
|
|
999
|
-
$('#fsTests-group, #kvTests-group, #aiTests-group, #txt2speechTests-group').prop('checked', isChecked);
|
|
1000
|
-
// Update the counter display
|
|
1001
|
-
updateMasterCheckboxState();
|
|
1002
|
-
});
|
|
1003
|
-
|
|
1004
|
-
// Function to update master checkbox state
|
|
1005
|
-
function updateMasterCheckboxState() {
|
|
1006
|
-
const totalCheckboxes = $('.test-checkbox').length;
|
|
1007
|
-
const checkedCheckboxes = $('.test-checkbox:checked').length;
|
|
1008
|
-
|
|
1009
|
-
// Update the counter display
|
|
1010
|
-
$('#test-counter').text(`${checkedCheckboxes} / ${totalCheckboxes}`);
|
|
1011
|
-
|
|
1012
|
-
if (checkedCheckboxes === 0) {
|
|
1013
|
-
$('#master-checkbox').prop('checked', false).prop('indeterminate', false);
|
|
1014
|
-
} else if (checkedCheckboxes === totalCheckboxes) {
|
|
1015
|
-
$('#master-checkbox').prop('checked', true).prop('indeterminate', false);
|
|
1016
|
-
} else {
|
|
1017
|
-
$('#master-checkbox').prop('checked', false).prop('indeterminate', true);
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
// Update master checkbox state when individual checkboxes change
|
|
1022
|
-
$(document).on('change', '.test-checkbox', function() {
|
|
1023
|
-
updateMasterCheckboxState();
|
|
1024
|
-
});
|
|
1025
|
-
|
|
1026
|
-
// Update master checkbox state when group checkboxes change
|
|
1027
|
-
$('#fsTests-group, #kvTests-group, #aiTests-group, #txt2speechTests-group').change(function() {
|
|
1028
|
-
updateMasterCheckboxState();
|
|
1029
|
-
});
|
|
1030
|
-
|
|
1031
|
-
// Initialize the counter display
|
|
1032
|
-
updateMasterCheckboxState();
|
|
1033
|
-
|
|
1034
|
-
// Login functionality
|
|
1035
|
-
$('#login-btn').click(async () => {
|
|
1036
|
-
try {
|
|
1037
|
-
$('#login-btn').prop('disabled', true);
|
|
1038
|
-
await puter.auth.signIn();
|
|
1039
|
-
await updateAuthUI();
|
|
1040
|
-
} catch (error) {
|
|
1041
|
-
console.error('Login error:', error);
|
|
1042
|
-
alert('Login failed. Please try again.');
|
|
1043
|
-
} finally {
|
|
1044
|
-
$('#login-btn').prop('disabled', false);
|
|
1045
|
-
}
|
|
1046
|
-
});
|
|
1047
|
-
|
|
1048
|
-
// Logout functionality
|
|
1049
|
-
$('#logout-link').click(async () => {
|
|
1050
|
-
try {
|
|
1051
|
-
await puter.auth.signOut();
|
|
1052
|
-
await updateAuthUI();
|
|
1053
|
-
} catch (error) {
|
|
1054
|
-
console.error('Logout error:', error);
|
|
1055
|
-
alert('Logout failed. Please try again.');
|
|
1056
|
-
}
|
|
1057
|
-
});
|
|
1058
|
-
|
|
1059
|
-
// Initialize auth UI after puter is loaded
|
|
1060
|
-
updateAuthUI();
|
|
1061
|
-
|
|
1062
|
-
// Settings modal functionality
|
|
1063
|
-
$('#settings-btn').click(() => {
|
|
1064
|
-
// Populate modal with current settings
|
|
1065
|
-
$('#puter-js-url').val(currentSettings.puterJsUrl);
|
|
1066
|
-
$('#api-origin').val(currentSettings.apiOrigin);
|
|
1067
|
-
$('#settings-modal').show();
|
|
1068
|
-
});
|
|
1069
|
-
|
|
1070
|
-
// Close modal
|
|
1071
|
-
$('.close, .btn-cancel').click(() => {
|
|
1072
|
-
$('#settings-modal').hide();
|
|
1073
|
-
});
|
|
1074
|
-
|
|
1075
|
-
// Save settings
|
|
1076
|
-
$('.btn-save').click(async () => {
|
|
1077
|
-
const newSettings = {
|
|
1078
|
-
puterJsUrl: $('#puter-js-url').val().trim(),
|
|
1079
|
-
apiOrigin: $('#api-origin').val().trim()
|
|
1080
|
-
};
|
|
1081
|
-
|
|
1082
|
-
// Validate URLs
|
|
1083
|
-
if (!newSettings.puterJsUrl || !newSettings.apiOrigin) {
|
|
1084
|
-
alert('Please provide both Puter.js URL and API Origin');
|
|
1085
|
-
return;
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
// Update current settings
|
|
1089
|
-
currentSettings = { ...newSettings };
|
|
1090
|
-
saveSettings();
|
|
1091
|
-
|
|
1092
|
-
// Reinitialize Puter with new settings
|
|
1093
|
-
await initializePuter();
|
|
1094
|
-
|
|
1095
|
-
$('#settings-modal').hide();
|
|
1096
|
-
});
|
|
1097
|
-
|
|
1098
|
-
// Close modal when clicking outside
|
|
1099
|
-
$(window).click((event) => {
|
|
1100
|
-
if (event.target === $('#settings-modal')[0]) {
|
|
1101
|
-
$('#settings-modal').hide();
|
|
1102
|
-
}
|
|
1103
|
-
});
|
|
1104
|
-
});
|
|
1105
|
-
|
|
1106
|
-
</script>
|
|
1107
|
-
</head>
|
|
1108
|
-
<body>
|
|
1109
|
-
|
|
1110
|
-
<nav>
|
|
1111
|
-
<label style="margin-left: 8px; margin-right: 10px; cursor: pointer; display: inline-flex; align-items: center;">
|
|
1112
|
-
<input type="checkbox" id="master-checkbox" style="margin-right: 5px; transform: scale(1.2);">
|
|
1113
|
-
</label>
|
|
1114
|
-
<span id="test-counter"></span>
|
|
1115
|
-
<div style="flex: 1; display: flex; align-items: center;">
|
|
1116
|
-
<button id="run-tests" style="margin-right: 10px;">Run Tests</button>
|
|
1117
|
-
<span id="reset-results" style="margin-right: 20px; cursor: pointer; color: #666; text-decoration: underline; font-size: 14px;">Reset results</span>
|
|
1118
|
-
<button id="settings-btn">Settings</button>
|
|
1119
|
-
<div id="auth-section">
|
|
1120
|
-
<button id="login-btn" style="display: none;">Login</button>
|
|
1121
|
-
<div id="user-info" style="display: none;">
|
|
1122
|
-
<span id="username"></span>
|
|
1123
|
-
<span id="logout-link">(logout)</span>
|
|
1124
|
-
</div>
|
|
1125
|
-
</div>
|
|
1126
|
-
</div>
|
|
1127
|
-
</nav>
|
|
1128
|
-
|
|
1129
|
-
<div id="progress-panel">
|
|
1130
|
-
<div class="progress-content">
|
|
1131
|
-
<div class="progress-left">
|
|
1132
|
-
<div class="current-test" id="current-test">Preparing tests...</div>
|
|
1133
|
-
<div class="progress-bar-container">
|
|
1134
|
-
<div class="progress-bar" id="progress-bar"></div>
|
|
1135
|
-
</div>
|
|
1136
|
-
<div class="elapsed-time" id="elapsed-time">Elapsed: 0s</div>
|
|
1137
|
-
</div>
|
|
1138
|
-
<div class="progress-right">
|
|
1139
|
-
<div class="progress-stats">
|
|
1140
|
-
<div class="progress-stat">
|
|
1141
|
-
<div class="progress-stat-number stat-passed" id="passed-count">0</div>
|
|
1142
|
-
<div class="progress-stat-label">Passed</div>
|
|
1143
|
-
</div>
|
|
1144
|
-
<div class="progress-stat">
|
|
1145
|
-
<div class="progress-stat-number stat-failed" id="failed-count">0</div>
|
|
1146
|
-
<div class="progress-stat-label">Failed</div>
|
|
1147
|
-
</div>
|
|
1148
|
-
<div class="progress-stat">
|
|
1149
|
-
<div class="progress-stat-number stat-total" id="total-count">0</div>
|
|
1150
|
-
<div class="progress-stat-label">Total</div>
|
|
1151
|
-
</div>
|
|
1152
|
-
</div>
|
|
1153
|
-
<div class="progress-percentage" id="progress-percentage">0%</div>
|
|
1154
|
-
</div>
|
|
1155
|
-
</div>
|
|
1156
|
-
</div>
|
|
1157
|
-
|
|
1158
|
-
<!-- Settings Modal -->
|
|
1159
|
-
<div id="settings-modal" class="modal">
|
|
1160
|
-
<div class="modal-content">
|
|
1161
|
-
<span class="close">×</span>
|
|
1162
|
-
<h2>Settings</h2>
|
|
1163
|
-
|
|
1164
|
-
<div class="setting-group">
|
|
1165
|
-
<label for="puter-js-url">Puter.js URL:</label>
|
|
1166
|
-
<input type="text" id="puter-js-url" placeholder="https://js.puter.com/v2/">
|
|
1167
|
-
</div>
|
|
1168
|
-
|
|
1169
|
-
<div class="setting-group">
|
|
1170
|
-
<label for="api-origin">API Origin:</label>
|
|
1171
|
-
<input type="text" id="api-origin" placeholder="https://api.puter.com">
|
|
1172
|
-
</div>
|
|
1173
|
-
|
|
1174
|
-
<div class="modal-buttons">
|
|
1175
|
-
<button class="btn-cancel">Cancel</button>
|
|
1176
|
-
<button class="btn-save">Save</button>
|
|
1177
|
-
</div>
|
|
1178
|
-
</div>
|
|
1179
|
-
</div>
|
|
1180
|
-
|
|
1181
|
-
<div id="tests"></div>
|
|
1182
|
-
</body>
|
|
1183
|
-
</html>
|