Skip to content
This repository was archived by the owner on Jul 2, 2026. It is now read-only.

Commit b3e0600

Browse files
committed
fix: adding window specific clean up
1 parent 47dbfc4 commit b3e0600

2 files changed

Lines changed: 105 additions & 2 deletions

File tree

src/test-setup-and-runner.ts

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { getVsixFilesFromDir } from './system-operations';
1313
import { TestConfig } from './core/types';
1414
import { createDefaultTestConfig, validateTestConfig, normalizePath } from './core/helpers';
1515
import { verifyAliasAndUserName } from './salesforce-components/authorization';
16+
import { retryOperation } from './retryUtils';
1617

1718
// Set Ubuntu Chrome arguments immediately when module loads
1819
if (process.platform === 'linux') {
@@ -213,6 +214,89 @@ class TestSetupAndRunner extends ExTester {
213214
}
214215
}
215216

217+
/**
218+
* Kills existing VS Code processes on Windows to prevent file locking issues during extension installation
219+
*/
220+
private async killExistingVSCodeProcesses(): Promise<void> {
221+
if (process.platform !== 'win32') {
222+
return;
223+
}
224+
225+
try {
226+
const { exec } = await import('child_process');
227+
const { promisify } = await import('util');
228+
const execAsync = promisify(exec);
229+
230+
log('Attempting to kill existing VS Code processes on Windows...');
231+
232+
// Kill VS Code processes on Windows
233+
const commands = [
234+
'taskkill /f /im Code.exe',
235+
'taskkill /f /im code.exe',
236+
'taskkill /f /im VSCode.exe',
237+
'taskkill /f /im electron.exe /fi "WINDOWTITLE eq Visual Studio Code*"',
238+
'taskkill /f /im node.exe /fi "COMMANDLINE eq *vscode*"'
239+
];
240+
241+
for (const command of commands) {
242+
try {
243+
await execAsync(command);
244+
log(`Executed: ${command}`);
245+
} catch (error) {
246+
// It's normal for taskkill to exit with code 1 if no processes are found
247+
log(`Command ${command} completed (processes may not have been running)`);
248+
}
249+
}
250+
251+
// Wait a moment for processes to fully terminate and release file locks
252+
await new Promise(resolve => setTimeout(resolve, 3000));
253+
log('VS Code process cleanup completed');
254+
255+
} catch (error) {
256+
log(`Warning: Could not kill VS Code processes: ${error}`);
257+
}
258+
}
259+
260+
/**
261+
* Cleans up Windows VS Code extension temporary files that may cause locking issues
262+
*/
263+
private async cleanupWindowsExtensionTempFiles(): Promise<void> {
264+
if (process.platform !== 'win32') {
265+
return;
266+
}
267+
268+
try {
269+
const { exec } = await import('child_process');
270+
const { promisify } = await import('util');
271+
const execAsync = promisify(exec);
272+
273+
log('Cleaning up Windows VS Code extension temporary files...');
274+
275+
// Clean up VS Code extension temporary files
276+
const cleanupCommands = [
277+
'del /f /q "%USERPROFILE%\\.vscode\\extensions\\*.vsctmp" 2>nul',
278+
'del /f /q "%USERPROFILE%\\.vscode\\extensions\\*.tmp" 2>nul',
279+
'rmdir /s /q "%TEMP%\\vscode-*" 2>nul',
280+
'rmdir /s /q "%TEMP%\\Code-*" 2>nul'
281+
];
282+
283+
for (const command of cleanupCommands) {
284+
try {
285+
await execAsync(command);
286+
log(`Executed cleanup: ${command}`);
287+
} catch (error) {
288+
// It's normal for cleanup commands to fail if files don't exist
289+
log(`Cleanup command completed: ${command}`);
290+
}
291+
}
292+
293+
log('Windows extension temp file cleanup completed');
294+
295+
} catch (error) {
296+
log(`Warning: Could not cleanup Windows extension temp files: ${error}`);
297+
}
298+
}
299+
216300
/**
217301
* Creates a Chrome wrapper script that forces Ubuntu-specific arguments
218302
*/
@@ -328,6 +412,12 @@ exec "${chromeExePath}" \\
328412
await this.createChromeWrapper();
329413
}
330414

415+
// Kill any existing VS Code processes on Windows before installing extensions
416+
if (process.platform === 'win32') {
417+
await this.killExistingVSCodeProcesses();
418+
await this.cleanupWindowsExtensionTempFiles();
419+
}
420+
331421
try {
332422
await this.installExtensions();
333423
} catch (error: unknown) {
@@ -491,7 +581,20 @@ exec "${chromeExePath}" \\
491581
}
492582
}
493583

494-
await this.installExtension(vsixPath);
584+
// Use retry logic for Windows to handle file locking issues
585+
if (process.platform === 'win32') {
586+
await retryOperation(
587+
async () => {
588+
// Add a small delay before each retry attempt to allow file handles to be released
589+
await new Promise(resolve => setTimeout(resolve, TestSetupAndRunner.RETRY_DELAY));
590+
await this.installExtension(vsixPath);
591+
},
592+
TestSetupAndRunner.MAX_RETRIES,
593+
`Failed to install extension ${path.basename(vsixPath)} after retries due to Windows file locking issues`
594+
);
595+
} else {
596+
await this.installExtension(vsixPath);
597+
}
495598
}
496599
}
497600

src/ui-interaction/modalDialog.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ import { log, pause, Duration } from '../core';
1717
* @throws Will throw an error if the modal dialog is undefined.
1818
*/
1919
export const clickButtonOnModalDialog = async (buttonText: string, failOnError = true): Promise<void> => {
20-
const modalDialog = new ModalDialog();
2120
await pause(Duration.seconds(2));
2221

2322
const pushButton = async () => {
2423
log(`clickButtonOnModalDialog() - Pushing button with text: "${buttonText}"`);
24+
const modalDialog = new ModalDialog();
2525
await pause(Duration.seconds(2)); // wait for the modal dialog to be visible
2626
await modalDialog.pushButton(buttonText);
2727
};

0 commit comments

Comments
 (0)