| """ |
| Admin Routes API Tests - Part 1: User and Role Management |
| |
| Tests for admin routes Part 1 (lines 1-545): |
| - Admin user CRUD: list, get, create, update, delete, last-login |
| - Admin role CRUD: list, get, create, update, delete |
| - Super admin authorization: require_super_admin dependency |
| - Error paths: 404 not found, 409 conflict, 403 unauthorized |
| - Governance enforcement: AUTONOMOUS required for create/delete |
| |
| Coverage target: 75%+ line coverage on admin_routes.py Part 1 |
| """ |
|
|
| import pytest |
| import uuid |
| from datetime import datetime, timezone |
| from fastapi import FastAPI, status |
| from fastapi.testclient import TestClient |
| from unittest.mock import MagicMock, AsyncMock, patch |
| from sqlalchemy import create_engine |
| from sqlalchemy.orm import sessionmaker, Session |
| from sqlalchemy.pool import StaticPool |
|
|
| |
| from api.admin_routes import router |
|
|
| |
| from core.models import ( |
| Base, User, AdminUser, AdminRole |
| ) |
|
|
| |
| from core.auth import get_password_hash |
|
|
|
|
| |
| |
| |
|
|
| @pytest.fixture(scope="function") |
| def test_db(): |
| """Create in-memory SQLite database for testing.""" |
| engine = create_engine( |
| "sqlite:///:memory:", |
| connect_args={"check_same_thread": False}, |
| poolclass=StaticPool |
| ) |
|
|
| |
| |
| from core.models import AdminUser, AdminRole, User |
|
|
| |
| AdminUser.__table__.create(bind=engine, checkfirst=True) |
| AdminRole.__table__.create(bind=engine, checkfirst=True) |
| User.__table__.create(bind=engine, checkfirst=True) |
|
|
| |
| TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) |
| db = TestingSessionLocal() |
|
|
| yield db |
|
|
| |
| db.close() |
| |
| AdminUser.__table__.drop(bind=engine) |
| AdminRole.__table__.drop(bind=engine) |
| User.__table__.drop(bind=engine) |
|
|
|
|
| @pytest.fixture(scope="function") |
| def test_app(test_db: Session): |
| """Create FastAPI app with admin routes for testing.""" |
| app = FastAPI() |
| app.include_router(router) |
|
|
| |
| from core.database import get_db |
|
|
| def override_get_db(): |
| try: |
| yield test_db |
| finally: |
| pass |
|
|
| app.dependency_overrides[get_db] = override_get_db |
|
|
| yield app |
|
|
| |
| app.dependency_overrides.clear() |
|
|
|
|
| @pytest.fixture(scope="function") |
| def client(test_app: FastAPI): |
| """Create TestClient for testing.""" |
| return TestClient(test_app) |
|
|
|
|
| @pytest.fixture(scope="function") |
| def mock_super_admin(test_db: Session) -> User: |
| """Create mock super_admin user for authorization tests""" |
| user = User( |
| id=str(uuid.uuid4()), |
| email="superadmin@test.com", |
| first_name="Super", |
| last_name="Admin", |
| name="Super Admin", |
| role="super_admin", |
| status="active", |
| email_verified=True |
| ) |
| test_db.add(user) |
| test_db.commit() |
| test_db.refresh(user) |
| return user |
|
|
|
|
| @pytest.fixture(scope="function") |
| def mock_team_lead(test_db: Session) -> User: |
| """Create mock team_lead user for authorization tests""" |
| user = User( |
| id=str(uuid.uuid4()), |
| email="teamlead@test.com", |
| first_name="Team", |
| last_name="Lead", |
| name="Team Lead", |
| role="team_lead", |
| status="active", |
| email_verified=True |
| ) |
| test_db.add(user) |
| test_db.commit() |
| test_db.refresh(user) |
| return user |
|
|
|
|
| @pytest.fixture(scope="function") |
| def mock_admin_role(test_db: Session) -> AdminRole: |
| """Create mock admin role for testing""" |
| role = AdminRole( |
| id=str(uuid.uuid4()), |
| name="Test Admin Role", |
| permissions={"users": True, "workflows": False, "reports": True}, |
| description="Test role for unit tests" |
| ) |
| test_db.add(role) |
| test_db.commit() |
| test_db.refresh(role) |
| return role |
|
|
|
|
| @pytest.fixture(scope="function") |
| def mock_admin_role_2(test_db: Session) -> AdminRole: |
| """Create second mock admin role for update/conflict tests""" |
| role = AdminRole( |
| id=str(uuid.uuid4()), |
| name="Another Test Role", |
| permissions={"users": False, "workflows": True, "reports": False}, |
| description="Second test role" |
| ) |
| test_db.add(role) |
| test_db.commit() |
| test_db.refresh(role) |
| return role |
|
|
|
|
| @pytest.fixture(scope="function") |
| def mock_admin_user(test_db: Session, mock_admin_role: AdminRole) -> AdminUser: |
| """Create mock admin user for testing""" |
| admin = AdminUser( |
| id=str(uuid.uuid4()), |
| email="testadmin@test.com", |
| name="Test Admin User", |
| password_hash=get_password_hash("TestPass123!"), |
| role_id=mock_admin_role.id, |
| status="active", |
| last_login=None, |
| created_at=datetime.now(timezone.utc) |
| ) |
| test_db.add(admin) |
| test_db.commit() |
| test_db.refresh(admin) |
| return admin |
|
|
|
|
| @pytest.fixture(scope="function") |
| def mock_inactive_admin_user(test_db: Session, mock_admin_role: AdminRole) -> AdminUser: |
| """Create inactive admin user for status tests""" |
| admin = AdminUser( |
| id=str(uuid.uuid4()), |
| email="inactiveadmin@test.com", |
| name="Inactive Admin", |
| password_hash=get_password_hash("TestPass123!"), |
| role_id=mock_admin_role.id, |
| status="inactive", |
| last_login=None, |
| created_at=datetime.now(timezone.utc) |
| ) |
| test_db.add(admin) |
| test_db.commit() |
| test_db.refresh(admin) |
| return admin |
|
|
|
|
| @pytest.fixture(scope="function") |
| def authenticated_client(client: TestClient, mock_super_admin: User): |
| """Create authenticated TestClient with admin user.""" |
| |
| from core.auth import get_current_user |
|
|
| def override_get_current_user(): |
| return mock_super_admin |
|
|
| |
| from api.admin_routes import require_super_admin |
|
|
| def override_require_super_admin(): |
| return mock_super_admin |
|
|
| |
| client.app.dependency_overrides[get_current_user] = override_get_current_user |
| client.app.dependency_overrides[require_super_admin] = override_require_super_admin |
|
|
| yield client |
|
|
| |
| client.app.dependency_overrides.clear() |
|
|
|
|
| |
| |
| |
|
|
| class TestAdminUserListing: |
| """Tests for GET /api/admin/users (list admin users)""" |
|
|
| def test_list_admin_users_success(self, authenticated_client: TestClient, test_db: Session, mock_admin_role: AdminRole): |
| """Test listing all admin users successfully""" |
| |
| admin1 = AdminUser( |
| id=str(uuid.uuid4()), |
| email="admin1@test.com", |
| name="Admin One", |
| password_hash=get_password_hash("Pass123!"), |
| role_id=mock_admin_role.id, |
| status="active" |
| ) |
| admin2 = AdminUser( |
| id=str(uuid.uuid4()), |
| email="admin2@test.com", |
| name="Admin Two", |
| password_hash=get_password_hash("Pass456!"), |
| role_id=mock_admin_role.id, |
| status="active" |
| ) |
| test_db.add(admin1) |
| test_db.add(admin2) |
| test_db.commit() |
|
|
| response = authenticated_client.get("/api/admin/users") |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert isinstance(data, list) |
| assert len(data) >= 2 |
|
|
| |
| for user in data: |
| assert "id" in user |
| assert "email" in user |
| assert "name" in user |
| assert "role_id" in user |
| assert "role_name" in user |
| assert "permissions" in user |
| assert "status" in user |
| assert "last_login" in user |
|
|
| def test_list_admin_users_empty(self, authenticated_client: TestClient, test_db: Session): |
| """Test listing admin users when none exist""" |
| |
| test_db.query(AdminUser).delete() |
| test_db.commit() |
|
|
| response = authenticated_client.get("/api/admin/users") |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert isinstance(data, list) |
| assert len(data) == 0 |
|
|
| def test_list_admin_users_with_roles_joined(self, authenticated_client: TestClient, test_db: Session, mock_admin_role: AdminRole): |
| """Test that role information is properly joined""" |
| admin = AdminUser( |
| id=str(uuid.uuid4()), |
| email="roleadmin@test.com", |
| name="Role Test Admin", |
| password_hash=get_password_hash("Pass123!"), |
| role_id=mock_admin_role.id, |
| status="active" |
| ) |
| test_db.add(admin) |
| test_db.commit() |
|
|
| response = authenticated_client.get("/api/admin/users") |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert len(data) >= 1 |
|
|
| |
| test_admin = next((u for u in data if u["email"] == "roleadmin@test.com"), None) |
| assert test_admin is not None |
| assert test_admin["role_name"] == mock_admin_role.name |
| assert test_admin["permissions"] == mock_admin_role.permissions |
|
|
|
|
| class TestAdminUserRetrieval: |
| """Tests for GET /api/admin/users/{admin_id} (get specific admin user)""" |
|
|
| def test_get_admin_user_success(self, authenticated_client: TestClient, test_db: Session, mock_admin_user: AdminUser): |
| """Test getting a specific admin user successfully""" |
| response = authenticated_client.get(f"/api/admin/users/{mock_admin_user.id}") |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert data["id"] == mock_admin_user.id |
| assert data["email"] == mock_admin_user.email |
| assert data["name"] == mock_admin_user.name |
| assert data["role_id"] == mock_admin_user.role_id |
| assert data["status"] == mock_admin_user.status |
| assert "last_login" in data |
| assert "created_at" in data |
|
|
| def test_get_admin_user_not_found(self, authenticated_client: TestClient): |
| """Test getting a non-existent admin user""" |
| fake_id = str(uuid.uuid4()) |
|
|
| response = authenticated_client.get(f"/api/admin/users/{fake_id}") |
|
|
| assert response.status_code == status.HTTP_404_NOT_FOUND |
| data = response.json() |
| assert "error" in data or "detail" in data |
|
|
| def test_get_admin_user_unauthorized(self, client: TestClient, test_db: Session, mock_team_lead: User): |
| """Test that non-super_admin users cannot access admin endpoints""" |
| |
| def override_get_current_user(): |
| return mock_team_lead |
|
|
| def override_require_super_admin(): |
| from core.base_routes import HTTPException |
| raise HTTPException( |
| status_code=status.HTTP_403_FORBIDDEN, |
| detail="Access denied: super_admin role required" |
| ) |
|
|
| client.app.dependency_overrides[client.app.dependencies[0].dependency] = override_get_current_user |
| from api.admin_routes import require_super_admin |
| client.app.dependency_overrides[require_super_admin] = override_require_super_admin |
|
|
| response = client.get(f"/api/admin/users/{uuid.uuid4()}") |
|
|
| assert response.status_code == status.HTTP_403_FORBIDDEN |
|
|
|
|
| class TestAdminUserCreation: |
| """Tests for POST /api/admin/users (create admin user)""" |
|
|
| def test_create_admin_user_success(self, authenticated_client: TestClient, test_db: Session, mock_admin_role: AdminRole): |
| """Test creating admin user successfully""" |
| request_data = { |
| "email": "newadmin@test.com", |
| "name": "New Admin", |
| "password": "SecurePass123!", |
| "role_id": mock_admin_role.id |
| } |
|
|
| response = authenticated_client.post("/api/admin/users", json=request_data) |
|
|
| assert response.status_code == status.HTTP_201_CREATED |
| data = response.json() |
| assert data["email"] == "newadmin@test.com" |
| assert data["name"] == "New Admin" |
| assert data["role_id"] == mock_admin_role.id |
| assert data["status"] == "active" |
| assert "id" in data |
|
|
| |
| admin = test_db.query(AdminUser).filter(AdminUser.email == "newadmin@test.com").first() |
| assert admin is not None |
| assert admin.password_hash != "SecurePass123!" |
|
|
| def test_create_admin_user_invalid_email(self, authenticated_client: TestClient): |
| """Test creating admin user with invalid email""" |
| request_data = { |
| "email": "not-an-email", |
| "name": "Test Admin", |
| "password": "SecurePass123!", |
| "role_id": str(uuid.uuid4()) |
| } |
|
|
| response = authenticated_client.post("/api/admin/users", json=request_data) |
|
|
| assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY |
|
|
| def test_create_admin_user_weak_password(self, authenticated_client: TestClient): |
| """Test creating admin user with weak password""" |
| request_data = { |
| "email": "test@test.com", |
| "name": "Test Admin", |
| "password": "short", |
| "role_id": str(uuid.uuid4()) |
| } |
|
|
| response = authenticated_client.post("/api/admin/users", json=request_data) |
|
|
| assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY |
|
|
| def test_create_admin_user_role_not_found(self, authenticated_client: TestClient): |
| """Test creating admin user with non-existent role""" |
| request_data = { |
| "email": "test@test.com", |
| "name": "Test Admin", |
| "password": "SecurePass123!", |
| "role_id": str(uuid.uuid4()) |
| } |
|
|
| response = authenticated_client.post("/api/admin/users", json=request_data) |
|
|
| assert response.status_code == status.HTTP_404_NOT_FOUND |
| data = response.json() |
| assert "role" in str(data).lower() or "field" in str(data).lower() |
|
|
| def test_create_admin_user_duplicate_email(self, authenticated_client: TestClient, test_db: Session, mock_admin_user: AdminUser): |
| """Test creating admin user with duplicate email""" |
| request_data = { |
| "email": mock_admin_user.email, |
| "name": "Duplicate Admin", |
| "password": "SecurePass123!", |
| "role_id": mock_admin_user.role_id |
| } |
|
|
| response = authenticated_client.post("/api/admin/users", json=request_data) |
|
|
| assert response.status_code == status.HTTP_409_CONFLICT |
| data = response.json() |
| assert "email" in str(data).lower() or "exists" in str(data).lower() |
|
|
| def test_create_admin_user_password_hashed(self, authenticated_client: TestClient, test_db: Session, mock_admin_role: AdminRole): |
| """Test that password is hashed during creation""" |
| request_data = { |
| "email": "hashed@test.com", |
| "name": "Hashed Admin", |
| "password": "PlainPassword123!", |
| "role_id": mock_admin_role.id |
| } |
|
|
| response = authenticated_client.post("/api/admin/users", json=request_data) |
|
|
| assert response.status_code == status.HTTP_201_CREATED |
|
|
| |
| admin = test_db.query(AdminUser).filter(AdminUser.email == "hashed@test.com").first() |
| assert admin is not None |
| assert admin.password_hash != "PlainPassword123!" |
| assert admin.password_hash.startswith("$2b$") or len(admin.password_hash) > 50 |
|
|
|
|
| class TestAdminUserUpdate: |
| """Tests for PATCH /api/admin/users/{admin_id} (update admin user)""" |
|
|
| def test_update_admin_user_name(self, authenticated_client: TestClient, test_db: Session, mock_admin_user: AdminUser): |
| """Test updating admin user name""" |
| response = authenticated_client.patch( |
| f"/api/admin/users/{mock_admin_user.id}", |
| json={"name": "Updated Name"} |
| ) |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert data["name"] == "Updated Name" |
|
|
| |
| test_db.refresh(mock_admin_user) |
| assert mock_admin_user.name == "Updated Name" |
|
|
| def test_update_admin_user_role(self, authenticated_client: TestClient, test_db: Session, mock_admin_user: AdminUser, mock_admin_role_2: AdminRole): |
| """Test updating admin user role""" |
| response = authenticated_client.patch( |
| f"/api/admin/users/{mock_admin_user.id}", |
| json={"role_id": mock_admin_role_2.id} |
| ) |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert data["role_id"] == mock_admin_role_2.id |
|
|
| |
| test_db.refresh(mock_admin_user) |
| assert mock_admin_user.role_id == mock_admin_role_2.id |
|
|
| def test_update_admin_user_status(self, authenticated_client: TestClient, test_db: Session, mock_admin_user: AdminUser): |
| """Test updating admin user status""" |
| response = authenticated_client.patch( |
| f"/api/admin/users/{mock_admin_user.id}", |
| json={"status": "inactive"} |
| ) |
|
|
| assert response.status_code == status.HTTP_200_OK |
|
|
| |
| test_db.refresh(mock_admin_user) |
| assert mock_admin_user.status == "inactive" |
|
|
| def test_update_admin_user_multiple_fields(self, authenticated_client: TestClient, test_db: Session, mock_admin_user: AdminUser, mock_admin_role_2: AdminRole): |
| """Test updating multiple admin user fields""" |
| response = authenticated_client.patch( |
| f"/api/admin/users/{mock_admin_user.id}", |
| json={ |
| "name": "Multi Update", |
| "role_id": mock_admin_role_2.id, |
| "status": "inactive" |
| } |
| ) |
|
|
| assert response.status_code == status.HTTP_200_OK |
|
|
| |
| test_db.refresh(mock_admin_user) |
| assert mock_admin_user.name == "Multi Update" |
| assert mock_admin_user.role_id == mock_admin_role_2.id |
| assert mock_admin_user.status == "inactive" |
|
|
| def test_update_admin_user_not_found(self, authenticated_client: TestClient): |
| """Test updating non-existent admin user""" |
| response = authenticated_client.patch( |
| f"/api/admin/users/{uuid.uuid4()}", |
| json={"name": "Test"} |
| ) |
|
|
| assert response.status_code == status.HTTP_404_NOT_FOUND |
|
|
| def test_update_admin_user_invalid_role(self, authenticated_client: TestClient, test_db: Session, mock_admin_user: AdminUser): |
| """Test updating admin user with invalid role""" |
| response = authenticated_client.patch( |
| f"/api/admin/users/{mock_admin_user.id}", |
| json={"role_id": str(uuid.uuid4())} |
| ) |
|
|
| assert response.status_code == status.HTTP_404_NOT_FOUND |
| data = response.json() |
| assert "role" in str(data).lower() |
|
|
|
|
| class TestAdminUserDeletion: |
| """Tests for DELETE /api/admin/users/{admin_id} (delete admin user)""" |
|
|
| def test_delete_admin_user_success(self, authenticated_client: TestClient, test_db: Session, mock_admin_user: AdminUser): |
| """Test deleting admin user successfully""" |
| admin_id = mock_admin_user.id |
|
|
| response = authenticated_client.delete(f"/api/admin/users/{admin_id}") |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert "deleted" in data["message"].lower() |
|
|
| |
| admin = test_db.query(AdminUser).filter(AdminUser.id == admin_id).first() |
| assert admin is None |
|
|
| def test_delete_admin_user_not_found(self, authenticated_client: TestClient): |
| """Test deleting non-existent admin user""" |
| response = authenticated_client.delete(f"/api/admin/users/{uuid.uuid4()}") |
|
|
| assert response.status_code == status.HTTP_404_NOT_FOUND |
|
|
|
|
| class TestAdminUserLastLogin: |
| """Tests for PATCH /api/admin/users/{admin_id}/last-login""" |
|
|
| def test_update_last_login_success(self, authenticated_client: TestClient, test_db: Session, mock_admin_user: AdminUser): |
| """Test updating last login timestamp""" |
| assert mock_admin_user.last_login is None |
|
|
| response = authenticated_client.patch(f"/api/admin/users/{mock_admin_user.id}/last-login") |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert "updated" in data["message"].lower() |
|
|
| |
| test_db.refresh(mock_admin_user) |
| assert mock_admin_user.last_login is not None |
| assert isinstance(mock_admin_user.last_login, datetime) |
|
|
| def test_update_last_login_not_found(self, authenticated_client: TestClient): |
| """Test updating last login for non-existent user""" |
| response = authenticated_client.patch(f"/api/admin/users/{uuid.uuid4()}/last-login") |
|
|
| assert response.status_code == status.HTTP_404_NOT_FOUND |
|
|
|
|
| |
| |
| |
|
|
| class TestAdminRoleListing: |
| """Tests for GET /api/admin/roles (list admin roles)""" |
|
|
| def test_list_admin_roles_success(self, authenticated_client: TestClient, test_db: Session, mock_admin_role: AdminRole, mock_admin_role_2: AdminRole): |
| """Test listing all admin roles successfully""" |
| response = authenticated_client.get("/api/admin/roles") |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert isinstance(data, list) |
| assert len(data) >= 2 |
|
|
| |
| for role in data: |
| assert "id" in role |
| assert "name" in role |
| assert "permissions" in role |
| assert "description" in role |
|
|
| def test_list_admin_roles_empty(self, authenticated_client: TestClient, test_db: Session): |
| """Test listing admin roles when none exist""" |
| |
| test_db.query(AdminRole).delete() |
| test_db.commit() |
|
|
| response = authenticated_client.get("/api/admin/roles") |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert isinstance(data, list) |
| assert len(data) == 0 |
|
|
|
|
| class TestAdminRoleRetrieval: |
| """Tests for GET /api/admin/roles/{role_id} (get specific admin role)""" |
|
|
| def test_get_admin_role_success(self, authenticated_client: TestClient, mock_admin_role: AdminRole): |
| """Test getting a specific admin role successfully""" |
| response = authenticated_client.get(f"/api/admin/roles/{mock_admin_role.id}") |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert data["id"] == mock_admin_role.id |
| assert data["name"] == mock_admin_role.name |
| assert data["permissions"] == mock_admin_role.permissions |
| assert data["description"] == mock_admin_role.description |
|
|
| def test_get_admin_role_not_found(self, authenticated_client: TestClient): |
| """Test getting a non-existent admin role""" |
| response = authenticated_client.get(f"/api/admin/roles/{uuid.uuid4()}") |
|
|
| assert response.status_code == status.HTTP_404_NOT_FOUND |
|
|
|
|
| class TestAdminRoleCreation: |
| """Tests for POST /api/admin/roles (create admin role)""" |
|
|
| def test_create_admin_role_success(self, authenticated_client: TestClient): |
| """Test creating admin role successfully""" |
| request_data = { |
| "name": "New Role", |
| "permissions": {"users": True, "reports": False}, |
| "description": "Test role" |
| } |
|
|
| response = authenticated_client.post("/api/admin/roles", json=request_data) |
|
|
| assert response.status_code == status.HTTP_201_CREATED |
| data = response.json() |
| assert data["name"] == "New Role" |
| assert data["permissions"] == {"users": True, "reports": False} |
| assert data["description"] == "Test role" |
| assert "id" in data |
|
|
| def test_create_admin_role_duplicate_name(self, authenticated_client: TestClient, test_db: Session, mock_admin_role: AdminRole): |
| """Test creating admin role with duplicate name""" |
| request_data = { |
| "name": mock_admin_role.name, |
| "permissions": {"users": True}, |
| "description": "Duplicate" |
| } |
|
|
| response = authenticated_client.post("/api/admin/roles", json=request_data) |
|
|
| assert response.status_code == status.HTTP_409_CONFLICT |
| data = response.json() |
| assert "name" in str(data).lower() or "exists" in str(data).lower() |
|
|
|
|
| class TestAdminRoleUpdate: |
| """Tests for PATCH /api/admin/roles/{role_id} (update admin role)""" |
|
|
| def test_update_admin_role_name(self, authenticated_client: TestClient, test_db: Session, mock_admin_role: AdminRole): |
| """Test updating admin role name""" |
| response = authenticated_client.patch( |
| f"/api/admin/roles/{mock_admin_role.id}", |
| json={"name": "Updated Name"} |
| ) |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert data["name"] == "Updated Name" |
|
|
| |
| test_db.refresh(mock_admin_role) |
| assert mock_admin_role.name == "Updated Name" |
|
|
| def test_update_admin_role_permissions(self, authenticated_client: TestClient, test_db: Session, mock_admin_role: AdminRole): |
| """Test updating admin role permissions""" |
| new_permissions = {"users": False, "admin": True} |
| response = authenticated_client.patch( |
| f"/api/admin/roles/{mock_admin_role.id}", |
| json={"permissions": new_permissions} |
| ) |
|
|
| assert response.status_code == status.HTTP_200_OK |
|
|
| |
| test_db.refresh(mock_admin_role) |
| assert mock_admin_role.permissions == new_permissions |
|
|
| def test_update_admin_role_description(self, authenticated_client: TestClient, test_db: Session, mock_admin_role: AdminRole): |
| """Test updating admin role description""" |
| response = authenticated_client.patch( |
| f"/api/admin/roles/{mock_admin_role.id}", |
| json={"description": "New description"} |
| ) |
|
|
| assert response.status_code == status.HTTP_200_OK |
|
|
| |
| test_db.refresh(mock_admin_role) |
| assert mock_admin_role.description == "New description" |
|
|
| def test_update_admin_role_duplicate_name(self, authenticated_client: TestClient, test_db: Session, mock_admin_role: AdminRole, mock_admin_role_2: AdminRole): |
| """Test updating role name to match existing role""" |
| response = authenticated_client.patch( |
| f"/api/admin/roles/{mock_admin_role.id}", |
| json={"name": mock_admin_role_2.name} |
| ) |
|
|
| assert response.status_code == status.HTTP_409_CONFLICT |
| data = response.json() |
| assert "name" in str(data).lower() or "exists" in str(data).lower() |
|
|
| def test_update_admin_role_not_found(self, authenticated_client: TestClient): |
| """Test updating non-existent admin role""" |
| response = authenticated_client.patch( |
| f"/api/admin/roles/{uuid.uuid4()}", |
| json={"name": "Test"} |
| ) |
|
|
| assert response.status_code == status.HTTP_404_NOT_FOUND |
|
|
|
|
| class TestAdminRoleDeletion: |
| """Tests for DELETE /api/admin/roles/{role_id} (delete admin role)""" |
|
|
| def test_delete_admin_role_success(self, authenticated_client: TestClient, test_db: Session): |
| """Test deleting admin role successfully""" |
| |
| role = AdminRole( |
| id=str(uuid.uuid4()), |
| name="Deletable Role", |
| permissions={"test": True}, |
| description="Role for deletion test" |
| ) |
| test_db.add(role) |
| test_db.commit() |
| role_id = role.id |
|
|
| response = authenticated_client.delete(f"/api/admin/roles/{role_id}") |
|
|
| assert response.status_code == status.HTTP_200_OK |
| data = response.json() |
| assert "deleted" in data["message"].lower() |
|
|
| |
| deleted_role = test_db.query(AdminRole).filter(AdminRole.id == role_id).first() |
| assert deleted_role is None |
|
|
| def test_delete_admin_role_not_found(self, authenticated_client: TestClient): |
| """Test deleting non-existent admin role""" |
| response = authenticated_client.delete(f"/api/admin/roles/{uuid.uuid4()}") |
|
|
| assert response.status_code == status.HTTP_404_NOT_FOUND |
|
|
| def test_delete_admin_role_in_use(self, authenticated_client: TestClient, test_db: Session, mock_admin_role: AdminRole, mock_admin_user: AdminUser): |
| """Test deleting role that is assigned to admin users""" |
| |
| response = authenticated_client.delete(f"/api/admin/roles/{mock_admin_role.id}") |
|
|
| assert response.status_code == status.HTTP_409_CONFLICT |
| data = response.json() |
| assert "user" in str(data).lower() or "assigned" in str(data).lower() |
|
|