diff --git a/ai-hub/integration_tests/test_node_registration.py b/ai-hub/integration_tests/test_node_registration.py new file mode 100644 index 0000000..7c812ae --- /dev/null +++ b/ai-hub/integration_tests/test_node_registration.py @@ -0,0 +1,63 @@ +import os +import httpx +import pytest +import uuid + +BASE_URL = os.getenv("SYNC_TEST_BASE_URL", "http://127.0.0.1:8002/api/v1") + +def _get_user_id() -> str: + """Gets the active super-admin or test runner user ID.""" + return os.getenv("SYNC_TEST_USER_ID", "c4401d34-8784-4d6e-93a0-c702bd202b66") + +def _headers(): + return {"X-User-ID": _get_user_id(), "Authorization": os.getenv("SYNC_TEST_AUTH_TOKEN", "")} + +def test_node_registration_flow(): + """ + Tests the Node Registration API flow from an Administrator standpoint. + 1. Registers a new test node with a unique ID and proper skill configurations. + 2. Verifies an invite token is generated strictly successfully. + 3. Confirms the Node metadata correctly persists and is accessible via the admin listing endpoint. + """ + user_id = _get_user_id() + node_id = f"test-integration-node-{uuid.uuid4().hex[:8]}" + display_name = f"Integration {node_id}" + + payload = { + "node_id": node_id, + "display_name": display_name, + "is_active": True, + "skill_config": {"shell": {"enabled": True}, "sync": {"enabled": True}} + } + + with httpx.Client(timeout=15.0) as client: + # Step 1: Register New Node + r_node = client.post( + f"{BASE_URL}/nodes/admin", + params={"admin_id": user_id}, + json=payload, + headers=_headers() + ) + + assert r_node.status_code == 200, f"Node registration failed unexpectedly: {r_node.text}" + + node_data = r_node.json() + assert node_data["node_id"] == node_id, "Payload collision: Returned node ID parameter does not match registration generation." + assert "invite_token" in node_data, "Critcal field drop: Invite token completely absent in valid creation serialization response" + assert len(node_data["invite_token"]) > 0, "Invite token string resolved fully blank." + + # Step 2: Ensure Node exists natively in the database via the admin nodes listing + r_list = client.get( + f"{BASE_URL}/nodes/admin", + params={"admin_id": user_id}, + headers=_headers() + ) + assert r_list.status_code == 200, "Node listing retrieval critically failed." + + node_list = r_list.json() + # Find our freshly pushed node in the complete node listing array map + matched_node = next((n for n in node_list if n["node_id"] == node_id), None) + + assert matched_node is not None, "Node completely failed to persist across DB contexts despite positive returned 200 serialization creation code." + assert matched_node["display_name"] == display_name, "Node display name persisted to DB unaligned." + assert matched_node["is_active"] is True, "Node default is_active flag failed persistence"