"""Tests for admin endpoints.""" import pytest from httpx import AsyncClient @pytest.mark.asyncio async def test_create_client(client: AsyncClient, admin_headers: dict): """Test creating a new client.""" response = await client.post( "/api/v1/admin/clients", json={ "name": "Acme Corp", "contact_email": "admin@acme.com", "billing_plan": "pro", }, headers=admin_headers, ) assert response.status_code == 201 data = response.json() assert data["name"] == "Acme Corp" assert data["contact_email"] == "admin@acme.com" assert data["billing_plan"] == "pro" assert data["status"] == "active" assert "id" in data @pytest.mark.asyncio async def test_create_client_unauthorized(client: AsyncClient): """Test creating client without auth fails.""" response = await client.post( "/api/v1/admin/clients", json={"name": "Test Corp"}, ) assert response.status_code == 422 # Missing header @pytest.mark.asyncio async def test_create_client_invalid_key(client: AsyncClient): """Test creating client with invalid key fails.""" response = await client.post( "/api/v1/admin/clients", json={"name": "Test Corp"}, headers={"X-Admin-Api-Key": "invalid-key"}, ) assert response.status_code == 401 @pytest.mark.asyncio async def test_list_clients(client: AsyncClient, admin_headers: dict): """Test listing clients.""" # Create a client first await client.post( "/api/v1/admin/clients", json={"name": "Test Corp 1"}, headers=admin_headers, ) await client.post( "/api/v1/admin/clients", json={"name": "Test Corp 2"}, headers=admin_headers, ) response = await client.get( "/api/v1/admin/clients", headers=admin_headers, ) assert response.status_code == 200 data = response.json() assert len(data) >= 2 @pytest.mark.asyncio async def test_create_instance(client: AsyncClient, admin_headers: dict): """Test creating an instance for a client.""" # Create client first client_response = await client.post( "/api/v1/admin/clients", json={"name": "Instance Test Corp"}, headers=admin_headers, ) client_id = client_response.json()["id"] # Create instance response = await client.post( f"/api/v1/admin/clients/{client_id}/instances", json={ "instance_id": "test-orchestrator", "region": "eu-west-1", }, headers=admin_headers, ) assert response.status_code == 201 data = response.json() assert data["instance_id"] == "test-orchestrator" assert data["region"] == "eu-west-1" assert data["license_status"] == "active" assert data["status"] == "pending" # Keys should be returned on creation assert "license_key" in data assert data["license_key"].startswith("lb_inst_") assert "hub_api_key" in data assert data["hub_api_key"].startswith("hk_") @pytest.mark.asyncio async def test_create_duplicate_instance(client: AsyncClient, admin_headers: dict): """Test that duplicate instance_id fails.""" # Create client client_response = await client.post( "/api/v1/admin/clients", json={"name": "Duplicate Test Corp"}, headers=admin_headers, ) client_id = client_response.json()["id"] # Create first instance await client.post( f"/api/v1/admin/clients/{client_id}/instances", json={"instance_id": "duplicate-test"}, headers=admin_headers, ) # Try to create duplicate response = await client.post( f"/api/v1/admin/clients/{client_id}/instances", json={"instance_id": "duplicate-test"}, headers=admin_headers, ) assert response.status_code == 409 @pytest.mark.asyncio async def test_rotate_license_key(client: AsyncClient, admin_headers: dict): """Test rotating a license key.""" # Create client and instance client_response = await client.post( "/api/v1/admin/clients", json={"name": "Rotate Test Corp"}, headers=admin_headers, ) client_id = client_response.json()["id"] instance_response = await client.post( f"/api/v1/admin/clients/{client_id}/instances", json={"instance_id": "rotate-test"}, headers=admin_headers, ) original_key = instance_response.json()["license_key"] # Rotate license response = await client.post( "/api/v1/admin/instances/rotate-test/rotate-license", headers=admin_headers, ) assert response.status_code == 200 data = response.json() assert data["license_key"].startswith("lb_inst_") assert data["license_key"] != original_key @pytest.mark.asyncio async def test_suspend_instance(client: AsyncClient, admin_headers: dict): """Test suspending an instance.""" # Create client and instance client_response = await client.post( "/api/v1/admin/clients", json={"name": "Suspend Test Corp"}, headers=admin_headers, ) client_id = client_response.json()["id"] await client.post( f"/api/v1/admin/clients/{client_id}/instances", json={"instance_id": "suspend-test"}, headers=admin_headers, ) # Suspend response = await client.post( "/api/v1/admin/instances/suspend-test/suspend", headers=admin_headers, ) assert response.status_code == 200 assert response.json()["status"] == "suspended" # Verify status get_response = await client.get( "/api/v1/admin/instances/suspend-test", headers=admin_headers, ) assert get_response.json()["license_status"] == "suspended" @pytest.mark.asyncio async def test_reactivate_instance(client: AsyncClient, admin_headers: dict): """Test reactivating a suspended instance.""" # Create client and instance client_response = await client.post( "/api/v1/admin/clients", json={"name": "Reactivate Test Corp"}, headers=admin_headers, ) client_id = client_response.json()["id"] await client.post( f"/api/v1/admin/clients/{client_id}/instances", json={"instance_id": "reactivate-test"}, headers=admin_headers, ) # Suspend await client.post( "/api/v1/admin/instances/reactivate-test/suspend", headers=admin_headers, ) # Reactivate response = await client.post( "/api/v1/admin/instances/reactivate-test/reactivate", headers=admin_headers, ) assert response.status_code == 200 assert response.json()["status"] == "pending" # Not activated yet