"""HTTP API v0 stub tests.""" from unittest.mock import patch from fastapi.testclient import TestClient from sandboxer.api.app import app from sandboxer.models import ActorType, Consumer, SandboxState, SandboxStatus, SnapshotRecord def test_list_sandboxes_empty() -> None: with patch("sandboxer.api.app._manager") as mgr: mgr.list.return_value = [] client = TestClient(app) assert client.get("/v1/sandboxes").json() == [] def test_get_sandbox_not_found() -> None: with patch("sandboxer.api.app._manager") as mgr: mgr.get.return_value = None client = TestClient(app) assert client.get("/v1/sandboxes/missing").status_code == 404 def test_create_sandbox() -> None: from datetime import UTC, datetime status = SandboxStatus( sandbox_id="abc12345", profile_id="profile.compose-e2e", extension_id="ext.compose-ssh", state=SandboxState.READY, consumer=Consumer(actor=ActorType.ADM, project="sand-boxer"), created_at=datetime.now(UTC), updated_at=datetime.now(UTC), ) with patch("sandboxer.api.app._manager") as mgr: mgr.create.return_value = status client = TestClient(app) resp = client.post( "/v1/sandboxes", json={ "profile": "profile.compose-e2e", "inputs": {"repo": "/tmp/x"}, "consumer": {"actor": "adm", "project": "sand-boxer"}, }, ) assert resp.status_code == 200 assert resp.json()["sandbox_id"] == "abc12345" def test_snapshot_sandbox() -> None: from datetime import UTC, datetime record = SnapshotRecord( snapshot_id="snap12345678", sandbox_id="abc12345", profile_id="profile.compose-checkpoint", extension_id="ext.compose-ssh", host="coulombcore", created_at=datetime.now(UTC), ) with patch("sandboxer.api.app._manager") as mgr: mgr.snapshot.return_value = record client = TestClient(app) resp = client.post("/v1/sandboxes/abc12345/snapshot") assert resp.status_code == 200 assert resp.json()["snapshot_id"] == "snap12345678" def test_restore_snapshot() -> None: from datetime import UTC, datetime status = SandboxStatus( sandbox_id="restored1", profile_id="profile.compose-checkpoint", extension_id="ext.compose-ssh", state=SandboxState.READY, consumer=Consumer(actor=ActorType.ADM, project="sand-boxer"), created_at=datetime.now(UTC), updated_at=datetime.now(UTC), ) with patch("sandboxer.api.app._manager") as mgr: mgr.restore.return_value = status client = TestClient(app) resp = client.post( "/v1/snapshots/snap12345678/restore", json={"consumer": {"actor": "adm", "project": "sand-boxer"}}, ) assert resp.status_code == 200 assert resp.json()["sandbox_id"] == "restored1" def test_recreate_sandbox() -> None: from datetime import UTC, datetime status = SandboxStatus( sandbox_id="new12345", profile_id="profile.compose-e2e", extension_id="ext.compose-ssh", state=SandboxState.READY, consumer=Consumer(actor=ActorType.ADM, project="sand-boxer"), created_at=datetime.now(UTC), updated_at=datetime.now(UTC), ) with patch("sandboxer.api.app._manager") as mgr: mgr.recreate.return_value = status client = TestClient(app) resp = client.post("/v1/sandboxes/abc12345/recreate") assert resp.status_code == 200 assert resp.json()["sandbox_id"] == "new12345" def test_extend_ttl() -> None: from datetime import UTC, datetime now = datetime.now(UTC) status = SandboxStatus( sandbox_id="abc12345", profile_id="profile.compose-e2e", extension_id="ext.compose-ssh", state=SandboxState.READY, consumer=Consumer(actor=ActorType.ADM, project="sand-boxer"), ttl="2h", expires_at=now, created_at=now, updated_at=now, ready_at=now, ) with patch("sandboxer.api.app._manager") as mgr: mgr.extend_ttl.return_value = status client = TestClient(app) resp = client.patch( "/v1/sandboxes/abc12345/ttl", json={"duration": "2h"}, ) assert resp.status_code == 200 assert resp.json()["ttl"] == "2h" def test_expire_sandboxes() -> None: from sandboxer.models import ExpireActionResult with patch("sandboxer.api.app._manager") as mgr: mgr.expire.return_value = [ ExpireActionResult(sandbox_id="x", reason="ttl", action="dry-run") ] client = TestClient(app) resp = client.post("/v1/sandboxes/expire") assert resp.status_code == 200 assert resp.json()[0]["action"] == "dry-run"