fix(tests): force exit after teardown to prevent hanging

Added 1-second grace period then force exit in global teardown. Background timers from registry/runtime modules were preventing Node.js from exiting naturally.
This commit is contained in:
ANGX
2026-01-27 09:26:12 +01:00
parent ca4ce7494e
commit c6ce514280
2 changed files with 65 additions and 2 deletions
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env node
/**
* Debug script to check what's keeping Node.js alive
*/
import { execSync } from 'child_process';
console.log('Running tests and checking for hanging handles...\n');
const startTime = Date.now();
// Run tests
try {
execSync('npm test', {
stdio: 'inherit',
timeout: 60000, // 60 second timeout
});
} catch (error) {
console.error('\n❌ Tests failed or timed out');
console.error(`Exit code: ${error.status}`);
}
const elapsed = Date.now() - startTime;
console.log(`\n⏱️ Total time: ${(elapsed / 1000).toFixed(2)}s`);
// Check active handles
console.log('\n🔍 Checking active handles...');
try {
const handles = process._getActiveHandles();
const requests = process._getActiveRequests();
console.log(`Active handles: ${handles.length}`);
console.log(`Active requests: ${requests.length}`);
if (handles.length > 0) {
console.log('\n📋 Active handles:');
handles.forEach((handle, i) => {
console.log(` ${i + 1}. ${handle.constructor.name}`);
});
}
if (requests.length > 0) {
console.log('\n📋 Active requests:');
requests.forEach((req, i) => {
console.log(` ${i + 1}. ${req.constructor.name}`);
});
}
} catch (err) {
console.error('Cannot check handles:', err.message);
}
console.log('\n✅ Check complete');
process.exit(0);
+11 -2
View File
@@ -4,6 +4,8 @@
*/
export default async function globalTeardown() {
console.log('\n🧹 Running global teardown...');
// Force garbage collection if available
if (global.gc) {
global.gc();
@@ -12,6 +14,13 @@ export default async function globalTeardown() {
// Give Node.js a moment to cleanup
await new Promise((resolve) => setTimeout(resolve, 100));
// Log completion
console.log('✓ Global teardown complete');
console.log('✓ Global teardown complete\n');
// Force exit to prevent hanging on background timers
// This is necessary because some modules (registry, runtime) have setInterval
// timers that may not cleanup properly in test environments
setTimeout(() => {
console.log('⚠️ Forcing process exit after 1s grace period');
process.exit(0);
}, 1000);
}