'running', 'pid' => $pid, 'log' => tail($logFile, 5)]); exit; } } $tests = $_GET['tests'] ?? ''; $testArgs = $tests ? implode(' ', array_map('escapeshellarg', explode(',', $tests))) : ''; $cmd = "nohup python3 $script $testArgs > $logFile 2>&1 & echo $!"; $pid = trim(shell_exec($cmd)); file_put_contents($pidFile, $pid); echo json_encode(['status' => 'started', 'pid' => $pid, 'tests' => $tests ?: 'all']); break; case 'status': if (file_exists($pidFile)) { $pid = trim(file_get_contents($pidFile)); $running = file_exists("/proc/$pid"); echo json_encode([ 'status' => $running ? 'running' : 'completed', 'pid' => $pid, 'log' => tail($logFile, 10) ]); } else { echo json_encode(['status' => 'idle']); } break; case 'results': if (file_exists($resultFile)) { echo file_get_contents($resultFile); } else { echo json_encode(['error' => 'No results yet']); } break; case 'screenshots': $dir = '/var/www/html/test-report/screenshots'; $files = array_filter(glob("$dir/pw-*.png"), 'is_file'); $list = array_map(function($f) { return ['name' => basename($f), 'size' => filesize($f), 'url' => '/test-report/screenshots/' . basename($f), 'time' => filemtime($f)]; }, $files); echo json_encode(array_values($list)); break; default: echo json_encode(['error' => 'Unknown action', 'actions' => ['run','status','results','screenshots']]); } function tail($file, $lines = 10) { if (!file_exists($file)) return ''; $f = file($file); return implode('', array_slice($f, -$lines)); }