Skip to content

Commit 3f8d0b9

Browse files
committed
render vm in webview
1 parent 3387a4e commit 3f8d0b9

3 files changed

Lines changed: 68 additions & 5 deletions

File tree

src/cli.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import path from 'path';
22
import * as vscode from 'vscode';
33
import EventEmitter from 'node:events';
44
import { logger } from './utils/logger';
5+
import { openTestDriverWebview } from './utils/webview';
56

67
// Import the TestDriver agent directly from the package (npm link preferred for local dev)
78
// eslint-disable-next-line @typescript-eslint/no-require-imports
@@ -121,8 +122,22 @@ export class TDInstance extends EventEmitter<EventsMap> {
121122

122123
private setupEventListeners() {
123124
this.agent.emitter.on('**', (data: any) => {
124-
console.log('event', this.agent.emitter.event, JSON.stringify(data ));
125-
this.emit(this.agent.emitter.event, data);
125+
const eventName = this.agent.emitter.event;
126+
console.log('event', eventName, JSON.stringify(data));
127+
this.emit(eventName, data);
128+
129+
// Listen for the show-window event and open a webview
130+
if (eventName === 'show-window') {
131+
try {
132+
const encodedData = encodeURIComponent(JSON.stringify(data));
133+
const urlToOpen = this.agent.debuggerUrl
134+
? `${this.agent.debuggerUrl}?data=${encodedData}`
135+
: `${data.url}?data=${encodedData}`;
136+
openTestDriverWebview(urlToOpen, 'TestDriver Window');
137+
} catch (err) {
138+
logger.error('Failed to open TestDriver webview', { error: err });
139+
}
140+
}
126141
});
127142

128143

src/tests.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,18 +147,31 @@ const setupRunProfiles = (controller: vscode.TestController, context?: vscode.Ex
147147
)!;
148148

149149
const relativePath = vscode.workspace.asRelativePath(test.uri!, false);
150+
151+
let instance: TDInstance | undefined;
150152
const abortController = new AbortController();
151-
token.onCancellationRequested(() => abortController.abort());
153+
154+
// Register cancellation handler to destroy the TDInstance
155+
const cancelListener = token.onCancellationRequested(() => {
156+
abortController.abort();
157+
if (instance && typeof instance.destroy === 'function') {
158+
try {
159+
instance.destroy();
160+
} catch (e) {
161+
logger.error('Error destroying TDInstance on cancel', e);
162+
}
163+
}
164+
});
152165

153166
try {
154167
await new Promise<void>((resolve) => {
155168
// Compose params with selected flags
156169
// params removed, now using command/flags in TDInstance
157-
const instance = new TDInstance(workspaceFolder.uri.fsPath, {
170+
instance = new TDInstance(workspaceFolder.uri.fsPath, {
158171
focus: false,
159172
command: 'run',
160-
flags: {'new-sandbox': true},
161173
file: relativePath.replace('testdriver/', ''),
174+
flags: {'new-sandbox': true},
162175
context,
163176
});
164177

@@ -196,6 +209,7 @@ const setupRunProfiles = (controller: vscode.TestController, context?: vscode.Ex
196209
});
197210
} finally {
198211
logger.info(`Test ${test.id} finished`);
212+
cancelListener.dispose();
199213
}
200214
});
201215

src/utils/webview.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import * as vscode from 'vscode';
2+
3+
export function openTestDriverWebview(url: string, title = 'TestDriver Window') {
4+
const panel = vscode.window.createWebviewPanel(
5+
'testdriverWebview',
6+
title,
7+
vscode.ViewColumn.Active,
8+
{
9+
enableScripts: true,
10+
retainContextWhenHidden: true,
11+
}
12+
);
13+
14+
// Simple HTML to embed the external URL in an iframe
15+
panel.webview.html = `
16+
<!DOCTYPE html>
17+
<html lang="en">
18+
<head>
19+
<meta charset="UTF-8">
20+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
21+
<title>${title}</title>
22+
<style>
23+
html, body, iframe { height: 100%; width: 100%; margin: 0; padding: 0; border: none; }
24+
iframe { border: none; }
25+
</style>
26+
</head>
27+
<body>
28+
<iframe src="${url}" width="100%" height="100%" allowfullscreen></iframe>
29+
</body>
30+
</html>
31+
`;
32+
33+
return panel;
34+
}

0 commit comments

Comments
 (0)