"""Integration tests using FastAPI TestClient.""" import pytest import os, json, time from pathlib import Path from fastapi.testclient import TestClient os.environ["HF_TOKEN"] = "" os.environ["OAUTH_CLIENT_ID"] = "" os.environ["OAUTH_CLIENT_SECRET"] = "" from app import app, session_store, STATE_DIR client = TestClient(app) for f in STATE_DIR.glob("*"): if f.is_file(): f.unlink() def auth(): token = session_store.create("tester", "tester") return {"Authorization": f"Bearer {token}"} class TestPublicEndpoints: def test_health(self): r = client.get("/health") assert r.status_code == 200 data = r.json() assert data["status"] == "healthy" assert data["app"] == "altamira-aade" def test_gatekeeper_check(self): r = client.post("/api/gatekeeper/check") assert r.status_code == 200 assert r.json()["hf_authenticated"] == False def test_index_html(self): r = client.get("/") assert r.status_code == 200 assert "text/html" in r.headers["content-type"] class TestAuthEndpoints: def test_oauth_login_not_configured(self): r = client.get("/api/auth/oauth/login") assert r.status_code == 200 assert r.json()["configured"] == False def test_login_requires_token(self): r = client.post("/api/auth/login", json={}) assert r.status_code == 400 def test_login_invalid_token(self): r = client.post("/api/auth/login", json={"hf_token": "bad_token"}) assert r.status_code == 401 def test_unauthorized_access(self): r = client.get("/api/projects") assert r.status_code == 401 def test_authorized_access(self): r = client.get("/api/projects", headers=auth()) assert r.status_code == 200 def test_logout(self): h = auth() r = client.post("/api/auth/logout", headers=h) assert r.status_code == 200 assert r.json()["status"] == "logged_out" def test_session_invalid_after_logout(self): h = auth() client.post("/api/auth/logout", headers=h) r = client.get("/api/projects", headers=h) assert r.status_code == 401 class TestProjectCRUD: def test_create_project(self): r = client.post("/api/projects", headers=auth(), json={"name": "test-project"}) assert r.status_code == 200 assert r.json()["name"] == "test-project" def test_create_duplicate(self): r = client.post("/api/projects", headers=auth(), json={"name": "test-project"}) assert r.status_code == 409 def test_list_projects(self): r = client.get("/api/projects", headers=auth()) assert r.status_code == 200 assert "test-project" in r.json() def test_delete_project(self): r = client.delete("/api/projects/test-project", headers=auth()) assert r.status_code == 200 assert r.json()["deleted"] == "test-project" def test_list_after_delete(self): r = client.get("/api/projects", headers=auth()) assert r.status_code == 200 assert "test-project" not in r.json() class TestResourceEndpoints: def test_save_resource(self): r = client.put("/api/resources/MY_CUSTOM_KEY", headers=auth(), json={ "value": "test-value-123", "scope": "core", "description": "Test key" }) assert r.status_code == 200 assert r.json()["saved"] == "MY_CUSTOM_KEY" assert r.json()["ping"]["status"] == "skipped" def test_list_resources(self): r = client.get("/api/resources", headers=auth()) assert r.status_code == 200 creds = r.json()["credentials"] assert "MY_CUSTOM_KEY" in creds def test_ping_resource(self): r = client.post("/api/resources/MY_CUSTOM_KEY/ping", headers=auth()) assert r.status_code == 200 assert r.json()["key"] == "MY_CUSTOM_KEY" def test_ping_unknown(self): r = client.post("/api/resources/NONEXISTENT/ping", headers=auth()) assert r.status_code == 404 def test_project_binding(self): r = client.post("/api/resources/bind/testproj2", headers=auth(), json={ "key": "MY_KEY", "value": "my_value" }) assert r.status_code == 200 assert r.json()["bound"] == "MY_KEY" def test_project_unbinding(self): r = client.post("/api/resources/unbind/testproj2", headers=auth(), json={ "key": "MY_KEY" }) assert r.status_code == 200 assert r.json()["unbound"] == "MY_KEY" def test_list_project_bindings(self): r = client.get("/api/resources/projects", headers=auth()) assert r.status_code == 200 def test_delete_resource(self): r = client.delete("/api/resources/MY_CUSTOM_KEY", headers=auth()) assert r.status_code == 200 assert r.json()["deleted"] == "MY_CUSTOM_KEY" class TestMonitorEndpoints: def test_get_manifest(self): r = client.get("/api/monitor/manifest", headers=auth()) assert r.status_code == 200 def test_update_manifest(self): r = client.post("/api/monitor/manifest/myproject", headers=auth(), json={ "status": "running", "version": "1.0", "message": "All good" }) assert r.status_code == 200 assert r.json()["saved"] == "myproject" def test_heartbeat(self): r = client.post("/api/monitor/heartbeat/myproject", headers=auth(), json={ "status": "running" }) assert r.status_code == 200 assert "pong" in r.json() def test_monitor_summary(self): r = client.get("/api/monitor/summary", headers=auth()) assert r.status_code == 200 assert "myproject" in r.json()["projects"] def test_throttle_status(self): r = client.get("/api/monitor/throttle", headers=auth()) assert r.status_code == 200 assert "multi_layer" in r.json() class TestAgentEndpoints: def test_agent_status(self): r = client.get("/api/agent/status", headers=auth()) assert r.status_code == 200 assert "key_pool" in r.json() def test_agent_tasks(self): r = client.get("/api/agent/tasks", headers=auth()) assert r.status_code == 200 assert "tasks" in r.json() def test_submit_task_no_prompt(self): r = client.post("/api/agent/submit", headers=auth(), json={}) assert r.status_code == 400 def test_submit_task(self): r = client.post("/api/agent/submit", headers=auth(), json={ "prompt": "Write hello world in Python" }) assert r.status_code == 200 assert "dag_id" in r.json() assert r.json()["status"] == "submitted" class TestSystemEndpoint: def test_system_info(self): r = client.get("/api/system", headers=auth()) assert r.status_code == 200 data = r.json() assert "platform" in data assert "python" in data assert "mode" in data assert data["mode"] == "AADE" def test_router_status(self): r = client.get("/api/router", headers=auth()) assert r.status_code == 200 assert "circuit_breaker" in r.json() class TestSandboxEndpoints: def test_list_sandboxes(self): r = client.get("/api/sandboxes", headers=auth()) assert r.status_code == 200 assert "local" in r.json() assert "hf_spaces" in r.json() class TestExternalTestingEndpoints: def test_artifact_upload(self): import base64 data = base64.b64encode(b"hello world").decode() r = client.post("/api/test/artifact/myproj", headers=auth(), json={ "filename": "test.txt", "data": data }) assert r.status_code == 200 assert r.json()["size"] == 11 def test_download_url(self): r = client.get("/api/test/download-url/myproj", headers=auth()) assert r.status_code == 200 assert "files" in r.json() def test_artifact_download(self): r = client.get("/api/test/artifact/myproj/test.txt", headers=auth()) assert r.status_code == 200 assert r.json()["filename"] == "test.txt" def test_webhook_no_url(self): r = client.post("/api/test/webhook/myproj", headers=auth(), json={}) assert r.status_code == 400 def test_github_actions_no_token(self): r = client.post("/api/test/github-actions/myproj", headers=auth(), json={ "repo": "testuser/testrepo" }) assert r.status_code == 400 class TestConsoleEndpoints: def test_console_exec(self): r = client.post("/api/console/exec", headers=auth(), json={ "command": "echo hello", "timeout": 5 }) assert r.status_code == 200 assert "hello" in r.json()["stdout"] class TestStateEndpoints: def test_get_state(self): r = client.get("/api/state", headers=auth()) assert r.status_code == 200 assert "state" in r.json() def test_sync_state(self): r = client.post("/api/state/sync", headers=auth()) assert r.status_code == 200 assert r.json()["status"] == "synced" def test_encrypt_decrypt(self): r = client.post("/api/state/encrypt", headers=auth(), json={"data": {"secret": "value"}}) assert r.status_code == 200 encrypted = r.json()["encrypted"] r2 = client.post("/api/state/decrypt", headers=auth(), json={"token": encrypted}) assert r2.status_code == 200 assert r2.json()["data"]["secret"] == "value" class TestCircuitBreaker: def test_reset_circuit(self): r = client.post("/api/router/circuit/reset", headers=auth()) assert r.status_code == 200 assert r.json()["status"] == "reset" def test_filter_context(self): r = client.post("/api/router/filter", headers=auth(), json={"text": "a" * 1000}) assert r.status_code == 200 assert r.json()["original_length"] == 1000