From bc14f2c72900fb1a4dd23480dd7f2461a7d09623 Mon Sep 17 00:00:00 2001 From: aitbc Date: Thu, 30 Apr 2026 10:53:29 +0200 Subject: [PATCH] Add unit tests for coordinator-api routers - Added test_routers_blockchain.py with tests for blockchain status and sync status - Added test_routers_governance.py with tests for governance proposals and voting - Added test_routers_marketplace.py with tests for marketplace listings - Added test_routers_agent.py with tests for agent list, register, and status - Added test_routers_payments.py with tests for payment creation and status This is Phase 2.2: Add tests for coordinator-api routers --- .../tests/test_routers_agent.py | 98 ++++++++++++++ .../tests/test_routers_blockchain.py | 123 ++++++++++++++++++ .../tests/test_routers_governance.py | 64 +++++++++ .../tests/test_routers_marketplace.py | 71 ++++++++++ .../tests/test_routers_payments.py | 69 ++++++++++ 5 files changed, 425 insertions(+) create mode 100644 apps/coordinator-api/tests/test_routers_agent.py create mode 100644 apps/coordinator-api/tests/test_routers_blockchain.py create mode 100644 apps/coordinator-api/tests/test_routers_governance.py create mode 100644 apps/coordinator-api/tests/test_routers_marketplace.py create mode 100644 apps/coordinator-api/tests/test_routers_payments.py diff --git a/apps/coordinator-api/tests/test_routers_agent.py b/apps/coordinator-api/tests/test_routers_agent.py new file mode 100644 index 00000000..ba778f96 --- /dev/null +++ b/apps/coordinator-api/tests/test_routers_agent.py @@ -0,0 +1,98 @@ +""" +Tests for agent router +""" + +import pytest +from unittest.mock import Mock, patch +from fastapi.testclient import TestClient + + +@pytest.mark.unit +class TestAgentRouter: + """Test agent router endpoints""" + + @patch('app.routers.agent_router.AITBCHTTPClient') + def test_agent_list(self, mock_client_class): + """Test getting agent list""" + # Setup mock + mock_client = Mock() + mock_client_class.return_value = mock_client + mock_client.get.return_value = { + "agents": [ + {"id": "agent1", "name": "Agent 1", "status": "active"}, + {"id": "agent2", "name": "Agent 2", "status": "idle"} + ], + "total": 2 + } + + # Import and test + from app.routers.agent_router import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.get("/agents") + assert response.status_code == 200 + data = response.json() + assert "agents" in data + assert data["total"] == 2 + + @patch('app.routers.agent_router.AITBCHTTPClient') + def test_agent_register(self, mock_client_class): + """Test registering a new agent""" + # Setup mock + mock_client = Mock() + mock_client_class.return_value = mock_client + mock_client.post.return_value = { + "id": "agent3", + "name": "Agent 3", + "status": "registered" + } + + # Import and test + from app.routers.agent_router import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.post("/agents", json={ + "name": "Agent 3", + "type": "compute", + "capabilities": ["gpu", "inference"] + }) + assert response.status_code == 200 + data = response.json() + assert data["id"] == "agent3" + assert data["status"] == "registered" + + @patch('app.routers.agent_router.AITBCHTTPClient') + def test_agent_status(self, mock_client_class): + """Test getting agent status""" + # Setup mock + mock_client = Mock() + mock_client_class.return_value = mock_client + mock_client.get.return_value = { + "id": "agent1", + "name": "Agent 1", + "status": "active", + "current_task": None, + "uptime": 3600 + } + + # Import and test + from app.routers.agent_router import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.get("/agents/agent1/status") + assert response.status_code == 200 + data = response.json() + assert data["id"] == "agent1" + assert data["status"] == "active" diff --git a/apps/coordinator-api/tests/test_routers_blockchain.py b/apps/coordinator-api/tests/test_routers_blockchain.py new file mode 100644 index 00000000..61cd38aa --- /dev/null +++ b/apps/coordinator-api/tests/test_routers_blockchain.py @@ -0,0 +1,123 @@ +""" +Tests for blockchain router +""" + +import pytest +from unittest.mock import Mock, patch +from fastapi.testclient import TestClient + + +@pytest.mark.unit +class TestBlockchainRouter: + """Test blockchain router endpoints""" + + @patch('app.routers.blockchain.settings') + @patch('app.routers.blockchain.AITBCHTTPClient') + def test_blockchain_status_connected(self, mock_client_class, mock_settings): + """Test blockchain status when connected""" + # Setup mocks + mock_settings.blockchain_rpc_url = "http://localhost:8082" + mock_client = Mock() + mock_client_class.return_value = mock_client + mock_client.get.return_value = { + "height": 100, + "hash": "abc123", + "timestamp": "2024-01-01T00:00:00Z", + "tx_count": 50 + } + + # Import and test + from app.routers.blockchain import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.get("/blockchain/status") + assert response.status_code == 200 + data = response.json() + assert data["status"] == "connected" + assert data["height"] == 100 + assert data["hash"] == "abc123" + + @patch('app.routers.blockchain.settings') + @patch('app.routers.blockchain.AITBCHTTPClient') + def test_blockchain_status_error(self, mock_client_class, mock_settings): + """Test blockchain status when RPC connection fails""" + # Setup mocks + mock_settings.blockchain_rpc_url = "http://localhost:8082" + mock_client = Mock() + mock_client_class.return_value = mock_client + from aitbc import NetworkError + mock_client.get.side_effect = NetworkError("Connection failed") + + # Import and test + from app.routers.blockchain import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.get("/blockchain/status") + assert response.status_code == 200 + data = response.json() + assert data["status"] == "error" + assert "RPC connection failed" in data["error"] + + @patch('app.routers.blockchain.settings') + @patch('app.routers.blockchain.AITBCHTTPClient') + def test_blockchain_sync_status_syncing(self, mock_client_class, mock_settings): + """Test blockchain sync status when syncing""" + # Setup mocks + mock_settings.blockchain_rpc_url = "http://localhost:8082" + mock_client = Mock() + mock_client_class.return_value = mock_client + mock_client.get.return_value = { + "syncing": True, + "current_block": 90, + "highest_block": 100 + } + + # Import and test + from app.routers.blockchain import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.get("/blockchain/sync-status") + assert response.status_code == 200 + data = response.json() + assert data["status"] == "syncing" + assert data["current_block"] == 90 + assert data["highest_block"] == 100 + + @patch('app.routers.blockchain.settings') + @patch('app.routers.blockchain.AITBCHTTPClient') + def test_blockchain_sync_status_synced(self, mock_client_class, mock_settings): + """Test blockchain sync status when synced""" + # Setup mocks + mock_settings.blockchain_rpc_url = "http://localhost:8082" + mock_client = Mock() + mock_client_class.return_value = mock_client + mock_client.get.return_value = { + "syncing": False, + "current_block": 100 + } + + # Import and test + from app.routers.blockchain import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.get("/blockchain/sync-status") + assert response.status_code == 200 + data = response.json() + assert data["status"] == "synced" + assert data["block"] == 100 diff --git a/apps/coordinator-api/tests/test_routers_governance.py b/apps/coordinator-api/tests/test_routers_governance.py new file mode 100644 index 00000000..98c2df5b --- /dev/null +++ b/apps/coordinator-api/tests/test_routers_governance.py @@ -0,0 +1,64 @@ +""" +Tests for governance router +""" + +import pytest +from unittest.mock import Mock, patch +from fastapi.testclient import TestClient + + +@pytest.mark.unit +class TestGovernanceRouter: + """Test governance router endpoints""" + + @patch('app.routers.governance.AITBCHTTPClient') + def test_governance_proposals_list(self, mock_client_class): + """Test getting governance proposals list""" + # Setup mock + mock_client = Mock() + mock_client_class.return_value = mock_client + mock_client.get.return_value = { + "proposals": [ + {"id": 1, "title": "Proposal 1", "status": "active"}, + {"id": 2, "title": "Proposal 2", "status": "pending"} + ] + } + + # Import and test + from app.routers.governance import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.get("/governance/proposals") + assert response.status_code == 200 + data = response.json() + assert "proposals" in data + assert len(data["proposals"]) == 2 + + @patch('app.routers.governance.AITBCHTTPClient') + def test_governance_vote(self, mock_client_class): + """Test voting on a governance proposal""" + # Setup mock + mock_client = Mock() + mock_client_class.return_value = mock_client + mock_client.post.return_value = { + "success": True, + "proposal_id": 1, + "vote": "yes" + } + + # Import and test + from app.routers.governance import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.post("/governance/proposals/1/vote", json={"vote": "yes"}) + assert response.status_code == 200 + data = response.json() + assert data["success"] is True diff --git a/apps/coordinator-api/tests/test_routers_marketplace.py b/apps/coordinator-api/tests/test_routers_marketplace.py new file mode 100644 index 00000000..0fbe664a --- /dev/null +++ b/apps/coordinator-api/tests/test_routers_marketplace.py @@ -0,0 +1,71 @@ +""" +Tests for marketplace router +""" + +import pytest +from unittest.mock import Mock, patch +from fastapi.testclient import TestClient + + +@pytest.mark.unit +class TestMarketplaceRouter: + """Test marketplace router endpoints""" + + @patch('app.routers.marketplace.AITBCHTTPClient') + def test_marketplace_list(self, mock_client_class): + """Test getting marketplace listings""" + # Setup mock + mock_client = Mock() + mock_client_class.return_value = mock_client + mock_client.get.return_value = { + "listings": [ + {"id": 1, "name": "GPU Instance 1", "price": 0.50}, + {"id": 2, "name": "GPU Instance 2", "price": 0.75} + ], + "total": 2 + } + + # Import and test + from app.routers.marketplace import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.get("/marketplace/listings") + assert response.status_code == 200 + data = response.json() + assert "listings" in data + assert data["total"] == 2 + + @patch('app.routers.marketplace.AITBCHTTPClient') + def test_marketplace_create_listing(self, mock_client_class): + """Test creating a marketplace listing""" + # Setup mock + mock_client = Mock() + mock_client_class.return_value = mock_client + mock_client.post.return_value = { + "id": 3, + "name": "GPU Instance 3", + "price": 1.00, + "status": "active" + } + + # Import and test + from app.routers.marketplace import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.post("/marketplace/listings", json={ + "name": "GPU Instance 3", + "price": 1.00, + "specs": {"gpu": "RTX 4090", "memory": "24GB"} + }) + assert response.status_code == 200 + data = response.json() + assert data["id"] == 3 + assert data["status"] == "active" diff --git a/apps/coordinator-api/tests/test_routers_payments.py b/apps/coordinator-api/tests/test_routers_payments.py new file mode 100644 index 00000000..5171178c --- /dev/null +++ b/apps/coordinator-api/tests/test_routers_payments.py @@ -0,0 +1,69 @@ +""" +Tests for payments router +""" + +import pytest +from unittest.mock import Mock, patch +from fastapi.testclient import TestClient + + +@pytest.mark.unit +class TestPaymentsRouter: + """Test payments router endpoints""" + + @patch('app.routers.payments.AITBCHTTPClient') + def test_payment_create(self, mock_client_class): + """Test creating a payment""" + # Setup mock + mock_client = Mock() + mock_client_class.return_value = mock_client + mock_client.post.return_value = { + "id": "payment1", + "amount": 100.0, + "currency": "USDC", + "status": "pending" + } + + # Import and test + from app.routers.payments import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.post("/payments", json={ + "amount": 100.0, + "currency": "USDC", + "recipient": "wallet123" + }) + assert response.status_code == 200 + data = response.json() + assert data["id"] == "payment1" + assert data["amount"] == 100.0 + + @patch('app.routers.payments.AITBCHTTPClient') + def test_payment_status(self, mock_client_class): + """Test getting payment status""" + # Setup mock + mock_client = Mock() + mock_client_class.return_value = mock_client + mock_client.get.return_value = { + "id": "payment1", + "amount": 100.0, + "status": "completed", + "transaction_hash": "0xabc123" + } + + # Import and test + from app.routers.payments import router + from app.main import create_app + + app = create_app() + app.include_router(router) + client = TestClient(app) + + response = client.get("/payments/payment1/status") + assert response.status_code == 200 + data = response.json() + assert data["status"] == "completed"