UNPKG

super-pancake-automation

Version:

A lightweight DOM-based UI automation framework using Chrome DevTools Protocol

129 lines (113 loc) 3.98 kB
// Simplified Chrome management for testing import { spawn } from 'child_process'; import WebSocket from 'ws'; import fetch from 'node-fetch'; import os from 'os'; let chromeProcess = null; export async function startTestChrome() { // Kill any existing Chrome processes try { const { execSync } = await import('child_process'); if (process.platform === 'win32') { // Windows: Kill Chrome processes with remote debugging execSync('taskkill /f /im chrome.exe /fi "COMMANDLINE eq *remote-debugging-port*" 2>nul', { stdio: 'ignore', shell: true }); } else { // Unix-like systems (macOS, Linux) execSync('pkill -f "Chrome.*--remote-debugging-port" 2>/dev/null || true', { stdio: 'ignore' }); } await new Promise(resolve => setTimeout(resolve, 2000)); } catch (error) { // Ignore cleanup errors } // Start Chrome with debugging enabled const chromePath = process.platform === 'win32' ? 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe' : process.platform === 'darwin' ? '/opt/homebrew/bin/google-chrome' : 'google-chrome'; chromeProcess = spawn(chromePath, [ '--headless=new', '--disable-gpu', '--no-sandbox', '--disable-dev-shm-usage', '--disable-web-security', '--remote-debugging-port=9222', '--disable-features=VizDisplayCompositor', '--enable-automation', '--disable-background-timer-throttling', '--disable-backgrounding-occluded-windows', '--disable-renderer-backgrounding', process.platform === 'win32' ? '--user-data-dir=' + os.tmpdir() + '\\chrome-test-' + Date.now() : '--user-data-dir=/tmp/chrome-test-' + Date.now() ], { stdio: 'pipe' }); // Wait for Chrome to start await new Promise(resolve => setTimeout(resolve, 3000)); // Try to connect for (let i = 0; i < 10; i++) { try { const response = await fetch('http://localhost:9222/json'); const targets = await response.json(); if (targets && targets.length > 0) { console.log('✅ Chrome started successfully'); return { port: 9222 }; } } catch (error) { console.log(`🔄 Waiting for Chrome... [${i + 1}/10]`); await new Promise(resolve => setTimeout(resolve, 1000)); } } throw new Error('Failed to start Chrome for testing'); } export async function stopTestChrome() { if (chromeProcess) { chromeProcess.kill('SIGTERM'); await new Promise(resolve => setTimeout(resolve, 1000)); if (!chromeProcess.killed) { chromeProcess.kill('SIGKILL'); } chromeProcess = null; } // Additional cleanup try { const { execSync } = await import('child_process'); if (process.platform === 'win32') { // Windows: Kill Chrome processes with remote debugging execSync('taskkill /f /im chrome.exe /fi "COMMANDLINE eq *remote-debugging-port*" 2>nul', { stdio: 'ignore', shell: true }); } else { // Unix-like systems (macOS, Linux) execSync('pkill -f "Chrome.*--remote-debugging-port" 2>/dev/null || true', { stdio: 'ignore' }); } } catch (error) { // Ignore cleanup errors } } export async function connectToTestChrome() { try { const response = await fetch('http://localhost:9222/json'); const targets = await response.json(); if (!targets || targets.length === 0) { throw new Error('No Chrome targets available'); } const wsUrl = targets[0].webSocketDebuggerUrl; const ws = new WebSocket(wsUrl); return new Promise((resolve, reject) => { const timeout = setTimeout(() => { ws.close(); reject(new Error('WebSocket connection timeout')); }, 5000); ws.once('open', () => { clearTimeout(timeout); resolve(ws); }); ws.once('error', (error) => { clearTimeout(timeout); reject(error); }); }); } catch (error) { throw new Error(`Failed to connect to Chrome: ${error.message}`); } }