electrobun 0.5.0-beta.0 → 0.7.0-beta.0

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.
Files changed (80) hide show
  1. package/{templates/multitab-browser/bun.lock → bun.lock} +20 -13
  2. package/dist/api/bun/core/BrowserView.ts +5 -1
  3. package/dist/api/bun/events/webviewEvents.ts +8 -0
  4. package/dist/api/bun/proc/native.ts +95 -21
  5. package/package.json +14 -16
  6. package/BETA_RELEASE.md +0 -67
  7. package/BUILD.md +0 -90
  8. package/LICENSE +0 -21
  9. package/README.md +0 -102
  10. package/debug.js +0 -5
  11. package/templates/hello-world/README.md +0 -57
  12. package/templates/hello-world/bun.lock +0 -225
  13. package/templates/hello-world/electrobun.config.ts +0 -28
  14. package/templates/hello-world/package.json +0 -16
  15. package/templates/hello-world/src/bun/index.ts +0 -15
  16. package/templates/hello-world/src/mainview/index.css +0 -124
  17. package/templates/hello-world/src/mainview/index.html +0 -46
  18. package/templates/hello-world/src/mainview/index.ts +0 -1
  19. package/templates/interactive-playground/README.md +0 -26
  20. package/templates/interactive-playground/assets/tray-icon.png +0 -0
  21. package/templates/interactive-playground/electrobun.config.ts +0 -36
  22. package/templates/interactive-playground/package-lock.json +0 -1112
  23. package/templates/interactive-playground/package.json +0 -15
  24. package/templates/interactive-playground/src/bun/demos/files.ts +0 -70
  25. package/templates/interactive-playground/src/bun/demos/menus.ts +0 -139
  26. package/templates/interactive-playground/src/bun/demos/rpc.ts +0 -83
  27. package/templates/interactive-playground/src/bun/demos/system.ts +0 -72
  28. package/templates/interactive-playground/src/bun/demos/updates.ts +0 -105
  29. package/templates/interactive-playground/src/bun/demos/windows.ts +0 -90
  30. package/templates/interactive-playground/src/bun/index.ts +0 -124
  31. package/templates/interactive-playground/src/bun/types/rpc.ts +0 -109
  32. package/templates/interactive-playground/src/mainview/components/EventLog.ts +0 -107
  33. package/templates/interactive-playground/src/mainview/components/Sidebar.ts +0 -65
  34. package/templates/interactive-playground/src/mainview/components/Toast.ts +0 -57
  35. package/templates/interactive-playground/src/mainview/demos/FileDemo.ts +0 -211
  36. package/templates/interactive-playground/src/mainview/demos/MenuDemo.ts +0 -102
  37. package/templates/interactive-playground/src/mainview/demos/RPCDemo.ts +0 -229
  38. package/templates/interactive-playground/src/mainview/demos/TrayDemo.ts +0 -132
  39. package/templates/interactive-playground/src/mainview/demos/WebViewDemo.ts +0 -465
  40. package/templates/interactive-playground/src/mainview/demos/WindowDemo.ts +0 -207
  41. package/templates/interactive-playground/src/mainview/index.css +0 -538
  42. package/templates/interactive-playground/src/mainview/index.html +0 -103
  43. package/templates/interactive-playground/src/mainview/index.ts +0 -238
  44. package/templates/multitab-browser/README.md +0 -34
  45. package/templates/multitab-browser/electrobun.config.ts +0 -32
  46. package/templates/multitab-browser/package-lock.json +0 -20
  47. package/templates/multitab-browser/package.json +0 -12
  48. package/templates/multitab-browser/src/bun/index.ts +0 -144
  49. package/templates/multitab-browser/src/bun/tabManager.ts +0 -200
  50. package/templates/multitab-browser/src/bun/types/rpc.ts +0 -78
  51. package/templates/multitab-browser/src/mainview/index.css +0 -487
  52. package/templates/multitab-browser/src/mainview/index.html +0 -94
  53. package/templates/multitab-browser/src/mainview/index.ts +0 -634
  54. package/templates/photo-booth/README.md +0 -108
  55. package/templates/photo-booth/bun.lock +0 -239
  56. package/templates/photo-booth/electrobun.config.ts +0 -32
  57. package/templates/photo-booth/package.json +0 -17
  58. package/templates/photo-booth/src/bun/index.ts +0 -92
  59. package/templates/photo-booth/src/mainview/index.css +0 -465
  60. package/templates/photo-booth/src/mainview/index.html +0 -124
  61. package/templates/photo-booth/src/mainview/index.ts +0 -499
  62. package/test-new-window-events.ts +0 -26
  63. package/test-new-window.html +0 -75
  64. package/test-npm-install.sh +0 -34
  65. package/tests/bun.lock +0 -14
  66. package/tests/electrobun.config.ts +0 -45
  67. package/tests/package-lock.json +0 -36
  68. package/tests/package.json +0 -13
  69. package/tests/src/bun/index.ts +0 -100
  70. package/tests/src/bun/test-runner.ts +0 -508
  71. package/tests/src/mainview/index.html +0 -110
  72. package/tests/src/mainview/index.ts +0 -458
  73. package/tests/src/mainview/styles/main.css +0 -451
  74. package/tests/src/testviews/tray-test.html +0 -57
  75. package/tests/src/testviews/webview-mask.html +0 -114
  76. package/tests/src/testviews/webview-navigation.html +0 -36
  77. package/tests/src/testviews/window-create.html +0 -17
  78. package/tests/src/testviews/window-events.html +0 -29
  79. package/tests/src/testviews/window-focus.html +0 -37
  80. package/tests/src/webviewtag/index.ts +0 -11
@@ -1,36 +0,0 @@
1
- {
2
- "name": "electrobun-tests",
3
- "version": "1.0.0",
4
- "lockfileVersion": 3,
5
- "requires": true,
6
- "packages": {
7
- "": {
8
- "name": "electrobun-tests",
9
- "version": "1.0.0",
10
- "dependencies": {
11
- "electrobun": "file:../"
12
- }
13
- },
14
- "..": {
15
- "version": "0.0.19-beta.118",
16
- "license": "MIT",
17
- "dependencies": {
18
- "@oneidentity/zstd-js": "^1.0.3",
19
- "archiver": "^7.0.1",
20
- "rpc-anywhere": "1.5.0",
21
- "tar": "^6.2.1"
22
- },
23
- "bin": {
24
- "electrobun": "bin/electrobun.cjs"
25
- },
26
- "devDependencies": {
27
- "@types/archiver": "^6.0.3",
28
- "@types/bun": "1.1.9"
29
- }
30
- },
31
- "node_modules/electrobun": {
32
- "resolved": "..",
33
- "link": true
34
- }
35
- }
36
- }
@@ -1,13 +0,0 @@
1
- {
2
- "name": "electrobun-tests",
3
- "version": "1.0.0",
4
- "description": "Interactive test harness for Electrobun",
5
- "type": "module",
6
- "scripts": {
7
- "start": "electrobun dev",
8
- "build:dev": "electrobun build"
9
- },
10
- "dependencies": {
11
- "electrobun": "file:../"
12
- }
13
- }
@@ -1,100 +0,0 @@
1
- import { BrowserWindow, BrowserView } from "electrobun/bun";
2
- import { TestRunner } from "./test-runner";
3
-
4
- // Define RPC schema for test communication
5
- export type TestRPCSchema = {
6
- bun: {
7
- requests: {
8
- runTest: {
9
- params: { testId: string };
10
- response: { success: boolean; message: string };
11
- };
12
- getTestStatus: {
13
- params: {};
14
- response: { tests: any[] };
15
- };
16
- cleanup: {
17
- params: {};
18
- response: { success: boolean; message: string };
19
- };
20
- };
21
- messages: {
22
- testEvent: { testId: string; status: string; data: any };
23
- };
24
- };
25
- webview: {
26
- requests: {
27
- markTestResult: {
28
- params: { testId: string; passed: boolean; notes?: string };
29
- response: { acknowledged: boolean };
30
- };
31
- };
32
- messages: {
33
- showInstructions: { testId: string; instructions: string[] };
34
- updateStatus: { testId: string; status: string; details?: string };
35
- };
36
- };
37
- };
38
-
39
- const testRunner = new TestRunner();
40
-
41
- // Create RPC handler
42
- const testRPC = BrowserView.defineRPC<TestRPCSchema>({
43
- maxRequestTime: 5000,
44
- handlers: {
45
- requests: {
46
- runTest: async ({ testId }) => {
47
- const result = await testRunner.runTest(testId);
48
- return result;
49
- },
50
- getTestStatus: async () => {
51
- return {
52
- tests: testRunner.getAllTestStatus()
53
- };
54
- },
55
- cleanup: async () => {
56
- try {
57
- await testRunner.cleanup();
58
- return { success: true, message: 'Cleanup completed successfully' };
59
- } catch (error) {
60
- console.error('Cleanup failed:', error);
61
- return { success: false, message: `Cleanup failed: ${error}` };
62
- }
63
- }
64
- },
65
- messages: {
66
- markTestResult: ({ testId, passed, notes }) => {
67
- testRunner.markManualTestResult(testId, passed, notes);
68
- console.log(`Manual test ${testId}: ${passed ? 'PASSED' : 'FAILED'}${notes ? ` - ${notes}` : ''}`);
69
- }
70
- }
71
- }
72
- });
73
-
74
- // Create main test window
75
- const mainWindow = new BrowserWindow({
76
- title: "Electrobun Test Harness",
77
- url: "views://mainview/index.html",
78
- renderer: "cef",
79
- frame: {
80
- x: 100,
81
- y: 100,
82
- width: 1200,
83
- height: 800
84
- },
85
- rpc: testRPC
86
- });
87
-
88
- // Set up test runner with main window reference
89
- testRunner.setMainWindow(mainWindow);
90
-
91
- // Initialize all tests
92
- testRunner.initialize();
93
-
94
- console.log("Electrobun Test Harness started");
95
- console.log("Main window created, loading test interface...");
96
-
97
- mainWindow.on("close", () => {
98
- console.log("Test harness closing, cleaning up...");
99
- testRunner.cleanup();
100
- });
@@ -1,508 +0,0 @@
1
- import { BrowserWindow, Tray } from "electrobun/bun";
2
- import type { TestRPCSchema } from "./index";
3
-
4
- export interface TestCase {
5
- id: string;
6
- name: string;
7
- category: string;
8
- type: 'auto' | 'manual' | 'hybrid';
9
- description?: string;
10
- setup: () => Promise<void> | void;
11
- cleanup?: () => Promise<void> | void;
12
- verify?: () => boolean; // Only for 'auto' tests
13
- instructions?: string[]; // For 'manual' tests
14
- status: 'pending' | 'running' | 'passed' | 'failed';
15
- lastResult?: { success: boolean; message?: string; timestamp: number };
16
- }
17
-
18
- export class TestRunner {
19
- private tests = new Map<string, TestCase>();
20
- private mainWindow: BrowserWindow | null = null;
21
- private testWindows: BrowserWindow[] = [];
22
- private trayInstance: Tray | null = null;
23
- private trayWindow: BrowserWindow | null = null;
24
-
25
- constructor() {
26
- this.registerAllTests();
27
- }
28
-
29
- setMainWindow(window: BrowserWindow) {
30
- this.mainWindow = window;
31
- }
32
-
33
- initialize() {
34
- console.log(`Registered ${this.tests.size} tests`);
35
-
36
- // Send initial test list to UI
37
- if (this.mainWindow) {
38
- setTimeout(() => {
39
- this.mainWindow!.webview.rpc?.send.updateStatus({
40
- testId: 'init',
41
- status: 'ready',
42
- details: `${this.tests.size} tests loaded`
43
- });
44
- }, 1000);
45
- }
46
- }
47
-
48
- private registerAllTests() {
49
- // Window Management Tests
50
- this.registerTest({
51
- id: 'window-creation',
52
- name: 'Window Creation',
53
- category: 'Windows',
54
- type: 'auto',
55
- description: 'Test creating and destroying windows',
56
- setup: async () => {
57
- const testWindow = new BrowserWindow({
58
- title: 'Test Window',
59
- frame: { width: 400, height: 300, x: 200, y: 200 },
60
- url: 'views://testviews/window-create.html'
61
- });
62
-
63
- this.testWindows.push(testWindow);
64
-
65
- // Auto-pass after window creation
66
- setTimeout(() => {
67
- this.markTestPassed('window-creation', 'Window created successfully');
68
- testWindow.close();
69
- }, 2000);
70
- }
71
- });
72
-
73
- this.registerTest({
74
- id: 'window-events',
75
- name: 'Window Move & Resize Events',
76
- category: 'Windows',
77
- type: 'auto',
78
- description: 'Test window event detection',
79
- setup: async () => {
80
- const testWindow = new BrowserWindow({
81
- title: 'Move and Resize Me!',
82
- frame: { width: 500, height: 400, x: 300, y: 200 },
83
- url: 'views://testviews/window-events.html'
84
- });
85
-
86
- this.testWindows.push(testWindow);
87
-
88
- let moveDetected = false;
89
- let resizeDetected = false;
90
-
91
- testWindow.on('move', ({data}) => {
92
- // if (!moveDetected) {
93
- moveDetected = true;
94
- const x = data?.x || 'unknown';
95
- const y = data?.y || 'unknown';
96
- testWindow.webview.executeJavascript(`
97
- document.getElementById('events').innerHTML = '<div>✅ Move detected: (${x}, ${y})</div>';
98
- `);
99
- this.updateTestStatus('window-events', moveDetected && resizeDetected);
100
- // }
101
- });
102
-
103
- testWindow.on('resize', ({data}) => {
104
- // if (!resizeDetected) {
105
- resizeDetected = true;
106
- const width = data?.width || 'unknown';
107
- const height = data?.height || 'unknown';
108
- testWindow.webview.executeJavascript(`
109
- document.getElementById('events').innerHTML = '<div>✅ Resize detected: ${width}x${height}</div>';
110
- `);
111
- this.updateTestStatus('window-events', moveDetected && resizeDetected);
112
- // }
113
- });
114
-
115
- testWindow.on('close', () => {
116
- if (moveDetected && resizeDetected) {
117
- this.markTestPassed('window-events', 'Both move and resize events detected');
118
- } else {
119
- this.markTestFailed('window-events', `Missing events - Move: ${moveDetected}, Resize: ${resizeDetected}`);
120
- }
121
- });
122
- }
123
- });
124
-
125
- // WebView Tests
126
- this.registerTest({
127
- id: 'webview-mask-layer',
128
- name: 'WebView Mask Layer',
129
- category: 'WebViews',
130
- type: 'manual',
131
- instructions: [
132
- 'A window will open with a WebView and a RED overlay button',
133
- 'Scroll the window up and down',
134
- 'Verify the RED button ALWAYS stays on top of the WebView',
135
- 'The button should NEVER disappear behind the WebView content',
136
- 'Click PASS if the button stays on top, FAIL if it goes behind'
137
- ],
138
- setup: async () => {
139
- const maskTestWindow = new BrowserWindow({
140
- title: 'Mask Test - SCROLL TO TEST',
141
- frame: { width: 700, height: 500, x: 400, y: 100 },
142
- url: 'views://testviews/webview-mask.html'
143
- });
144
-
145
- this.testWindows.push(maskTestWindow);
146
- }
147
- });
148
-
149
- this.registerTest({
150
- id: 'webview-navigation',
151
- name: 'WebView Navigation',
152
- category: 'WebViews',
153
- type: 'hybrid',
154
- instructions: [
155
- 'A WebView will load example.com',
156
- 'Verify the page content loads correctly',
157
- 'Try navigating to different URLs if possible',
158
- 'Check that navigation events are detected (shown below)'
159
- ],
160
- setup: async () => {
161
- const navTestWindow = new BrowserWindow({
162
- title: 'WebView Navigation Test',
163
- frame: { width: 800, height: 600, x: 200, y: 150 },
164
- url: 'views://testviews/webview-navigation.html'
165
- });
166
-
167
- this.testWindows.push(navTestWindow);
168
-
169
- // Auto-detect navigation events
170
- navTestWindow.webview.on('did-navigate', ({data: {detail: url}}) => {
171
- navTestWindow.webview.executeJavascript(`
172
- document.getElementById('nav-events').innerHTML +=
173
- '<div>✅ Navigation: ${url} at ' + new Date().toLocaleTimeString() + '</div>';
174
- `);
175
- this.markTestPassed('webview-navigation', `Navigation detected to: ${url}`);
176
- });
177
- }
178
- });
179
-
180
- // System Integration Tests
181
- this.registerTest({
182
- id: 'system-tray',
183
- name: 'System Tray',
184
- category: 'System',
185
- type: 'manual',
186
- instructions: [
187
- 'Look for a test tray icon in your system tray/menu bar',
188
- 'Click the tray icon to open the menu',
189
- 'Try clicking "Test Item 1" and "Test Item 2"',
190
- 'Try the submenu items',
191
- 'Verify menu items work and events are logged below'
192
- ],
193
- setup: async () => {
194
- this.trayInstance = new Tray({
195
- title: "Test",
196
- image: ""
197
- });
198
-
199
- // Set up tray event listener
200
- this.trayInstance.on('tray-clicked', (eventData) => {
201
- console.log('Tray clicked:', eventData);
202
- // TODO: Note: trim() is currently necessary even though nothing is being trimmed.
203
- // Could be an issue with this version of bun or something else.
204
- const action = eventData?.data?.action?.trim();
205
-
206
- switch (action) {
207
- case 'test-item-1':
208
- this.logTrayEvent("Test Item 1 clicked");
209
- break;
210
- case 'test-item-2':
211
- this.logTrayEvent("Test Item 2 clicked");
212
- break;
213
- case 'submenu-item-a':
214
- this.logTrayEvent("Submenu Item A clicked");
215
- break;
216
- case 'submenu-item-b':
217
- this.logTrayEvent("Submenu Item B clicked");
218
- break;
219
- case 'mark-passed':
220
- this.markTestPassed('system-tray', 'User confirmed tray functionality works');
221
- break;
222
- default:
223
- console.log(`Unknown tray action: "${action}"`);
224
- }
225
- });
226
-
227
- // Set the menu separately
228
- this.trayInstance.setMenu([
229
- {
230
- type: "normal",
231
- label: "Test Item 1",
232
- action: "test-item-1"
233
- },
234
- {
235
- type: "normal",
236
- label: "Test Item 2",
237
- action: "test-item-2"
238
- },
239
- { type: "separator" },
240
- {
241
- type: "normal",
242
- label: "Submenu Test",
243
- submenu: [
244
- {
245
- type: "normal",
246
- label: "Submenu Item A",
247
- action: "submenu-item-a"
248
- },
249
- {
250
- type: "normal",
251
- label: "Submenu Item B",
252
- action: "submenu-item-b"
253
- }
254
- ]
255
- },
256
- { type: "separator" },
257
- {
258
- type: "normal",
259
- label: "Mark Tray Test as Passed",
260
- action: "mark-passed"
261
- }
262
- ]);
263
-
264
- // Show tray test window with instructions
265
- this.trayWindow = new BrowserWindow({
266
- title: 'Tray Test Instructions',
267
- frame: { width: 500, height: 400, x: 100, y: 300 },
268
- url: 'views://testviews/tray-test.html'
269
- });
270
-
271
- this.testWindows.push(this.trayWindow);
272
- },
273
- cleanup: async () => {
274
- if (this.trayInstance) {
275
- this.trayInstance.remove();
276
- this.trayInstance = null;
277
- }
278
- this.trayWindow = null;
279
- }
280
- });
281
-
282
- // Multi-window test
283
- this.registerTest({
284
- id: 'multi-window',
285
- name: 'Multi-Window Management',
286
- category: 'Windows',
287
- type: 'manual',
288
- instructions: [
289
- 'Multiple windows will be created',
290
- 'Try focusing different windows by clicking on them',
291
- 'Verify window focus changes are detected',
292
- 'Try overlapping and arranging windows',
293
- 'Check that each window behaves independently'
294
- ],
295
- setup: async () => {
296
- // Create multiple test windows
297
- for (let i = 1; i <= 3; i++) {
298
- const testWindow = new BrowserWindow({
299
- title: `Test Window ${i}`,
300
- frame: {
301
- width: 300,
302
- height: 250,
303
- x: 200 + (i * 50),
304
- y: 200 + (i * 50)
305
- },
306
- url: `views://testviews/window-focus.html?num=${i}`
307
- });
308
-
309
- this.testWindows.push(testWindow);
310
-
311
- let focusCount = 0;
312
- testWindow.on('focus', () => {
313
- focusCount++;
314
- testWindow.webview.executeJavascript(`
315
- document.getElementById('focus-status').textContent = 'Focused';
316
- document.getElementById('focus-count').textContent = 'Focus events: ${focusCount}';
317
- document.body.style.borderLeft = '5px solid green';
318
- `);
319
- });
320
-
321
- testWindow.on('blur', () => {
322
- testWindow.webview.executeJavascript(`
323
- document.getElementById('focus-status').textContent = 'Not Focused';
324
- document.body.style.borderLeft = '5px solid gray';
325
- `);
326
- });
327
- }
328
-
329
- // Auto-pass after windows are created
330
- setTimeout(() => {
331
- this.markTestPassed('multi-window', 'Multiple windows created successfully');
332
- }, 1000);
333
- }
334
- });
335
- }
336
-
337
- private registerTest(test: Omit<TestCase, 'status' | 'lastResult'>) {
338
- this.tests.set(test.id, {
339
- ...test,
340
- status: 'pending'
341
- });
342
- }
343
-
344
- async runTest(testId: string): Promise<{ success: boolean; message: string }> {
345
- const test = this.tests.get(testId);
346
- if (!test) {
347
- return { success: false, message: `Test ${testId} not found` };
348
- }
349
-
350
- test.status = 'running';
351
- this.notifyStatusChange(testId);
352
-
353
- try {
354
- await test.setup();
355
-
356
- if (test.type === 'auto' && test.verify) {
357
- const result = test.verify();
358
- if (result) {
359
- this.markTestPassed(testId, 'Auto-verification passed');
360
- } else {
361
- this.markTestFailed(testId, 'Auto-verification failed');
362
- }
363
- }
364
-
365
- return { success: true, message: `Test ${testId} setup completed` };
366
- } catch (error) {
367
- console.error(`Test ${testId} failed:`, error);
368
- this.markTestFailed(testId, `Setup failed: ${error.message}`);
369
- return { success: false, message: error.message };
370
- }
371
- }
372
-
373
- markManualTestResult(testId: string, passed: boolean, notes?: string) {
374
- if (passed) {
375
- this.markTestPassed(testId, notes || 'Manual verification passed');
376
- } else {
377
- this.markTestFailed(testId, notes || 'Manual verification failed');
378
- }
379
- }
380
-
381
- private markTestPassed(testId: string, message: string) {
382
- const test = this.tests.get(testId);
383
- if (test) {
384
- test.status = 'passed';
385
- test.lastResult = { success: true, message, timestamp: Date.now() };
386
- this.notifyStatusChange(testId);
387
- console.log(`✅ Test PASSED: ${test.name} - ${message}`);
388
- }
389
- }
390
-
391
- private markTestFailed(testId: string, message: string) {
392
- const test = this.tests.get(testId);
393
- if (test) {
394
- test.status = 'failed';
395
- test.lastResult = { success: false, message, timestamp: Date.now() };
396
- this.notifyStatusChange(testId);
397
- console.log(`❌ Test FAILED: ${test.name} - ${message}`);
398
- }
399
- }
400
-
401
- private updateTestStatus(testId: string, success: boolean) {
402
- if (success) {
403
- this.markTestPassed(testId, 'All conditions met');
404
- }
405
- }
406
-
407
- private notifyStatusChange(testId: string) {
408
- if (this.mainWindow) {
409
- const test = this.tests.get(testId);
410
- this.mainWindow.webview.rpc?.send.updateStatus({
411
- testId,
412
- status: test?.status || 'unknown',
413
- details: test?.lastResult?.message
414
- });
415
- }
416
- }
417
-
418
- private logTrayEvent(message: string) {
419
- console.log(`Tray event: ${message}`);
420
- // Use the stored tray window reference
421
- if (this.trayWindow) {
422
- try {
423
- // Add a small delay to ensure the DOM is ready and use a more robust approach
424
- setTimeout(() => {
425
- this.trayWindow?.webview.executeJavascript(`
426
- console.log('Trying to update tray events with: ${message}');
427
-
428
- // Wait for DOM to be ready
429
- function updateTrayEvents() {
430
- const eventsDiv = document.getElementById('tray-events');
431
- console.log('Found tray-events div:', eventsDiv);
432
-
433
- if (eventsDiv) {
434
- const eventHtml = '<div class="event-item">✅ ${message} at ' + new Date().toLocaleTimeString() + '</div>';
435
- console.log('Adding event HTML:', eventHtml);
436
- eventsDiv.innerHTML += eventHtml;
437
- console.log('Updated tray events successfully');
438
- } else {
439
- console.error('tray-events element not found in tray window');
440
- // Try to find any element with id containing 'tray'
441
- const allElements = document.querySelectorAll('[id*="tray"]');
442
- console.log('Elements with tray in id:', allElements);
443
- }
444
- }
445
-
446
- if (document.readyState === 'loading') {
447
- document.addEventListener('DOMContentLoaded', updateTrayEvents);
448
- } else {
449
- updateTrayEvents();
450
- }
451
- `);
452
- }, 100);
453
- } catch (error) {
454
- console.error('Failed to update tray window:', error);
455
- }
456
- } else {
457
- console.error('Tray window not available');
458
- }
459
- }
460
-
461
- getAllTestStatus() {
462
- return Array.from(this.tests.values()).map(test => ({
463
- id: test.id,
464
- name: test.name,
465
- category: test.category,
466
- type: test.type,
467
- status: test.status,
468
- description: test.description,
469
- instructions: test.instructions,
470
- lastResult: test.lastResult
471
- }));
472
- }
473
-
474
- async cleanup() {
475
- console.log('Cleaning up test runner...');
476
-
477
- // Close all test windows
478
- for (const window of this.testWindows) {
479
- try {
480
- window.close();
481
- } catch (e) {
482
- // Window might already be closed
483
- }
484
- }
485
- this.testWindows = [];
486
-
487
- // Remove tray
488
- if (this.trayInstance) {
489
- this.trayInstance.remove();
490
- this.trayInstance = null;
491
- }
492
-
493
- // Run individual test cleanup
494
- for (const test of this.tests.values()) {
495
- if (test.cleanup) {
496
- try {
497
- await test.cleanup();
498
- } catch (e) {
499
- console.warn(`Cleanup failed for test ${test.id}:`, e);
500
- }
501
- }
502
-
503
- // Reset test status to pending
504
- test.status = 'pending';
505
- delete test.lastResult;
506
- }
507
- }
508
- }