Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 64 additions & 4 deletions tests/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// This file runs before all tests

import { beforeAll, afterAll } from 'vitest';
import { execSync } from 'child_process';
import { execSync, execFileSync } from 'child_process';

const isWindows = process.platform === 'win32';

// Track if we're in cleanup mode
let isCleaningUp = false;
Expand All @@ -17,7 +19,7 @@ afterAll(() => {
});

/**
* Cleanup function to kill all Firefox and geckodriver processes
* Cleanup function to kill leftover test Firefox and geckodriver processes
* This ensures no zombie processes are left after test runs
*/
function cleanup() {
Expand All @@ -26,6 +28,15 @@ function cleanup() {
}
isCleaningUp = true;

if (isWindows) {
cleanupWindows();
} else {
cleanupUnix();
}
isCleaningUp = false;
}

function cleanupUnix() {
try {
// Find Firefox processes started with --marionette (test instances)
const firefoxPids = execSync('pgrep -f "firefox.*marionette" || true', {
Expand Down Expand Up @@ -57,8 +68,57 @@ function cleanup() {
console.log('✅ Global cleanup: All test Firefox processes terminated');
} catch {
// Ignore errors - processes might already be dead
} finally {
isCleaningUp = false;
}
}

/**
* Windows only. Retrieve all process ids matching the provided name and
* optional command line pattern.
*/
function findWindowsProcessIds(imageName: string, commandLinePattern?: string): number[] {
const filter = commandLinePattern
? `Name='${imageName}' AND CommandLine LIKE '%${commandLinePattern}%'`
: `Name='${imageName}'`;
const script =
`Get-CimInstance Win32_Process -Filter "${filter}" | ` +
'Select-Object -ExpandProperty ProcessId';
const output = execFileSync(
'powershell.exe',
['-NoProfile', '-NonInteractive', '-Command', script],
{ encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true }
);
return output
.split(/\r?\n/)
.map((line) => line.trim())
.filter((line) => /^\d+$/.test(line))
.map(Number);
}

function cleanupWindows() {
try {
const firefoxPids = findWindowsProcessIds('firefox.exe', '--marionette');
for (const pid of firefoxPids) {
try {
// /T kills the whole process tree, replacing the Unix child-kill step
execSync(`taskkill /PID ${pid} /T /F`, { stdio: 'ignore' });
Comment thread
f3tchcodes marked this conversation as resolved.
} catch {
// Ignore errors - process might already be dead
}
}

for (const pid of findWindowsProcessIds('geckodriver.exe')) {
try {
execSync(`taskkill /PID ${pid} /T /F`, { stdio: 'ignore' });
} catch {
// Ignore errors - process might already be dead
}
}

if (firefoxPids.length > 0) {
console.log('✅ Global cleanup: All test Firefox processes terminated');
}
} catch {
// Ignore errors - processes might already be dead
}
}

Expand Down