electrobun 0.5.0-beta.0 → 0.6.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.
- package/{templates/multitab-browser/bun.lock → bun.lock} +20 -13
- package/dist/api/bun/proc/native.ts +84 -16
- package/package.json +14 -16
- package/BETA_RELEASE.md +0 -67
- package/BUILD.md +0 -90
- package/LICENSE +0 -21
- package/README.md +0 -102
- package/debug.js +0 -5
- package/templates/hello-world/README.md +0 -57
- package/templates/hello-world/bun.lock +0 -225
- package/templates/hello-world/electrobun.config.ts +0 -28
- package/templates/hello-world/package.json +0 -16
- package/templates/hello-world/src/bun/index.ts +0 -15
- package/templates/hello-world/src/mainview/index.css +0 -124
- package/templates/hello-world/src/mainview/index.html +0 -46
- package/templates/hello-world/src/mainview/index.ts +0 -1
- package/templates/interactive-playground/README.md +0 -26
- package/templates/interactive-playground/assets/tray-icon.png +0 -0
- package/templates/interactive-playground/electrobun.config.ts +0 -36
- package/templates/interactive-playground/package-lock.json +0 -1112
- package/templates/interactive-playground/package.json +0 -15
- package/templates/interactive-playground/src/bun/demos/files.ts +0 -70
- package/templates/interactive-playground/src/bun/demos/menus.ts +0 -139
- package/templates/interactive-playground/src/bun/demos/rpc.ts +0 -83
- package/templates/interactive-playground/src/bun/demos/system.ts +0 -72
- package/templates/interactive-playground/src/bun/demos/updates.ts +0 -105
- package/templates/interactive-playground/src/bun/demos/windows.ts +0 -90
- package/templates/interactive-playground/src/bun/index.ts +0 -124
- package/templates/interactive-playground/src/bun/types/rpc.ts +0 -109
- package/templates/interactive-playground/src/mainview/components/EventLog.ts +0 -107
- package/templates/interactive-playground/src/mainview/components/Sidebar.ts +0 -65
- package/templates/interactive-playground/src/mainview/components/Toast.ts +0 -57
- package/templates/interactive-playground/src/mainview/demos/FileDemo.ts +0 -211
- package/templates/interactive-playground/src/mainview/demos/MenuDemo.ts +0 -102
- package/templates/interactive-playground/src/mainview/demos/RPCDemo.ts +0 -229
- package/templates/interactive-playground/src/mainview/demos/TrayDemo.ts +0 -132
- package/templates/interactive-playground/src/mainview/demos/WebViewDemo.ts +0 -465
- package/templates/interactive-playground/src/mainview/demos/WindowDemo.ts +0 -207
- package/templates/interactive-playground/src/mainview/index.css +0 -538
- package/templates/interactive-playground/src/mainview/index.html +0 -103
- package/templates/interactive-playground/src/mainview/index.ts +0 -238
- package/templates/multitab-browser/README.md +0 -34
- package/templates/multitab-browser/electrobun.config.ts +0 -32
- package/templates/multitab-browser/package-lock.json +0 -20
- package/templates/multitab-browser/package.json +0 -12
- package/templates/multitab-browser/src/bun/index.ts +0 -144
- package/templates/multitab-browser/src/bun/tabManager.ts +0 -200
- package/templates/multitab-browser/src/bun/types/rpc.ts +0 -78
- package/templates/multitab-browser/src/mainview/index.css +0 -487
- package/templates/multitab-browser/src/mainview/index.html +0 -94
- package/templates/multitab-browser/src/mainview/index.ts +0 -634
- package/templates/photo-booth/README.md +0 -108
- package/templates/photo-booth/bun.lock +0 -239
- package/templates/photo-booth/electrobun.config.ts +0 -32
- package/templates/photo-booth/package.json +0 -17
- package/templates/photo-booth/src/bun/index.ts +0 -92
- package/templates/photo-booth/src/mainview/index.css +0 -465
- package/templates/photo-booth/src/mainview/index.html +0 -124
- package/templates/photo-booth/src/mainview/index.ts +0 -499
- package/test-new-window-events.ts +0 -26
- package/test-new-window.html +0 -75
- package/test-npm-install.sh +0 -34
- package/tests/bun.lock +0 -14
- package/tests/electrobun.config.ts +0 -45
- package/tests/package-lock.json +0 -36
- package/tests/package.json +0 -13
- package/tests/src/bun/index.ts +0 -100
- package/tests/src/bun/test-runner.ts +0 -508
- package/tests/src/mainview/index.html +0 -110
- package/tests/src/mainview/index.ts +0 -458
- package/tests/src/mainview/styles/main.css +0 -451
- package/tests/src/testviews/tray-test.html +0 -57
- package/tests/src/testviews/webview-mask.html +0 -114
- package/tests/src/testviews/webview-navigation.html +0 -36
- package/tests/src/testviews/window-create.html +0 -17
- package/tests/src/testviews/window-events.html +0 -29
- package/tests/src/testviews/window-focus.html +0 -37
- package/tests/src/webviewtag/index.ts +0 -11
package/tests/package-lock.json
DELETED
|
@@ -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
|
-
}
|
package/tests/package.json
DELETED
|
@@ -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
|
-
}
|
package/tests/src/bun/index.ts
DELETED
|
@@ -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
|
-
}
|