netgescon-day0/tests/Feature/ControlTowerPollCommandTest.php

152 lines
5.2 KiB
PHP

<?php
use Illuminate\Support\Facades\Http;
use Illuminate\Console\Command;
beforeEach(function () {
Http::preventStrayRequests();
});
it('verifies process environment HOME PATH AGY_MODE, absolute path, and preserves stdout/stderr', function () {
$taskId = 'task-test-env-001';
Http::fake([
'http://192.168.0.53:4174/api/tasks/next*' => Http::response(['task' => ['id' => $taskId, 'title' => 'Test Env', 'description' => 'Desc']], 200),
'http://192.168.0.53:4174/api/reports' => Http::response(['id' => 'rep-env-123'], 201),
'http://192.168.0.53:4174/api/tasks/status' => Http::response(['status' => 'done'], 200),
'http://192.168.0.53:4174/api/machines/heartbeat' => Http::response(['status' => 'online'], 200),
]);
$mockScript = tempnam(sys_get_temp_dir(), 'mock_wrapper_env_') . '.sh';
$scriptContent = <<<'BASH'
#!/usr/bin/env bash
if [ -n "${ANTIGRAVITY_AGENT:-}" ] || [ -n "${ANTIGRAVITY_CSRF_TOKEN:-}" ]; then
echo "ERROR: ANTIGRAVITY_ variables found" >&2
exit 1
fi
if [ "$AGY_MODE" != "plan" ]; then
echo "ERROR: AGY_MODE != plan" >&2
exit 1
fi
if [ -z "$HOME" ] || [ -z "$PATH" ]; then
echo "ERROR: HOME or PATH missing" >&2
exit 1
fi
cat << JSON
{
"ok": true,
"parsed": {
"task_id": "task-test-env-001",
"esito_205": "riuscito",
"repository": "ssh://git@192.168.0.53:2222/michele/netgescon-day0.git",
"branch": "stabilization/205-zero",
"commit": "0ac85f8c8502d9bb4e015ee6b15a452ef3fd1422",
"consolidated_unit_id": "SMOKE-24825CBB",
"blocco_dati": "no",
"dates_used": ["2026-08-10"],
"test_eseguiti": ["env test"],
"note": ["ENV_OK"],
"absorbed_legacy_fragments": ["frag-001"],
"open_legacy_fragments": [],
"raw_text": "ENV_OK"
}
}
JSON
exit 0
BASH;
file_put_contents($mockScript, $scriptContent);
chmod($mockScript, 0755);
$exitCode = $this->artisan('netgescon:control-tower-poll', [
'--task-id' => $taskId,
'--wrapper-script' => $mockScript,
])->run();
@unlink($mockScript);
expect($exitCode)->toBe(Command::SUCCESS);
Http::assertSent(function ($request) use ($taskId) {
return str_contains($request->url(), '/api/reports') &&
($request['task_id'] ?? null) === $taskId &&
str_contains($request['raw_text'] ?? '', 'ENV_OK');
});
});
it('does not publish report when wrapper exit code is non-zero', function () {
$taskId = 'task-test-err-001';
Http::fake([
'http://192.168.0.53:4174/api/tasks/next*' => Http::response(['task' => ['id' => $taskId]], 200),
]);
$mockScript = tempnam(sys_get_temp_dir(), 'mock_wrapper_err_') . '.sh';
file_put_contents($mockScript, "#!/usr/bin/env bash\necho 'Fatal wrapper error' >&2\nexit 1\n");
chmod($mockScript, 0755);
$exitCode = $this->artisan('netgescon:control-tower-poll', [
'--task-id' => $taskId,
'--wrapper-script' => $mockScript,
])->run();
@unlink($mockScript);
expect($exitCode)->toBe(Command::FAILURE);
Http::assertNotSent(function ($request) {
return str_contains($request->url(), '/api/reports');
});
});
it('publishes report when wrapper returns valid parsed payload', function () {
$taskId = 'task-test-001';
Http::fake([
'http://192.168.0.53:4174/api/tasks/next*' => Http::response(['task' => ['id' => $taskId, 'title' => 'Test Task', 'description' => 'Test Desc']], 200),
'http://192.168.0.53:4174/api/reports' => Http::response(['id' => 'rep-123'], 201),
'http://192.168.0.53:4174/api/tasks/status' => Http::response(['status' => 'done'], 200),
'http://192.168.0.53:4174/api/machines/heartbeat' => Http::response(['status' => 'online'], 200),
]);
$mockScript = tempnam(sys_get_temp_dir(), 'mock_wrapper_') . '.sh';
$jsonOutput = json_encode([
'ok' => true,
'parsed' => [
'task_id' => $taskId,
'esito_205' => 'riuscito',
'repository' => 'ssh://git@192.168.0.53:2222/michele/netgescon-day0.git',
'branch' => 'stabilization/205-zero',
'commit' => 'a159c03799bd942bb6c8a74e50eb9ddf9a74aefb',
'consolidated_unit_id' => '1545',
'blocco_dati' => 'no',
'dates_used' => ['2026-08-10'],
'test_eseguiti' => ['NETTOWER_AGY_ULTRA_WRAPPER_OK'],
'note' => ['Test OK'],
'absorbed_legacy_fragments' => ['id_cond=12'],
'open_legacy_fragments' => [],
'raw_text' => 'NETTOWER_AGY_ULTRA_WRAPPER_OK',
],
], JSON_UNESCAPED_SLASHES);
file_put_contents($mockScript, "#!/usr/bin/env bash\ncat - >/dev/null\necho '{$jsonOutput}'\nexit 0\n");
chmod($mockScript, 0755);
$exitCode = $this->artisan('netgescon:control-tower-poll', [
'--task-id' => $taskId,
'--wrapper-script' => $mockScript,
])->run();
@unlink($mockScript);
expect($exitCode)->toBe(Command::SUCCESS);
Http::assertSent(function ($request) use ($taskId) {
return str_contains($request->url(), '/api/reports') &&
($request['task_id'] ?? null) === $taskId &&
str_contains($request['raw_text'] ?? '', 'NETTOWER_AGY_ULTRA_WRAPPER_OK');
});
});