# tests/unit/services/test_admin_platform_service.py """ Unit tests for AdminPlatformService. Tests the admin platform assignment service operations. """ import pytest from app.exceptions import AdminOperationException, CannotModifySelfException, ValidationException from app.services.admin_platform_service import AdminPlatformService @pytest.mark.unit @pytest.mark.admin class TestAdminPlatformServiceAssign: """Test AdminPlatformService.assign_admin_to_platform.""" def test_assign_admin_to_platform_success( self, db, test_platform_admin, test_platform, test_super_admin ): """Test successfully assigning an admin to a platform.""" service = AdminPlatformService() assignment = service.assign_admin_to_platform( db=db, admin_user_id=test_platform_admin.id, platform_id=test_platform.id, assigned_by_user_id=test_super_admin.id, ) assert assignment is not None assert assignment.user_id == test_platform_admin.id assert assignment.platform_id == test_platform.id assert assignment.is_active is True assert assignment.assigned_by_user_id == test_super_admin.id def test_assign_admin_user_not_found(self, db, test_platform, test_super_admin): """Test assigning non-existent user raises error.""" service = AdminPlatformService() with pytest.raises(ValidationException) as exc: service.assign_admin_to_platform( db=db, admin_user_id=99999, platform_id=test_platform.id, assigned_by_user_id=test_super_admin.id, ) assert "User not found" in str(exc.value) def test_assign_admin_not_admin_role( self, db, test_vendor_user, test_platform, test_super_admin ): """Test assigning non-admin user raises error.""" service = AdminPlatformService() with pytest.raises(ValidationException) as exc: service.assign_admin_to_platform( db=db, admin_user_id=test_vendor_user.id, platform_id=test_platform.id, assigned_by_user_id=test_super_admin.id, ) assert "must be an admin" in str(exc.value) def test_assign_super_admin_raises_error( self, db, test_super_admin, test_platform ): """Test assigning super admin raises error.""" service = AdminPlatformService() with pytest.raises(ValidationException) as exc: service.assign_admin_to_platform( db=db, admin_user_id=test_super_admin.id, platform_id=test_platform.id, assigned_by_user_id=test_super_admin.id, ) assert "Super admins don't need platform assignments" in str(exc.value) def test_assign_platform_not_found( self, db, test_platform_admin, test_super_admin ): """Test assigning to non-existent platform raises error.""" service = AdminPlatformService() with pytest.raises(ValidationException) as exc: service.assign_admin_to_platform( db=db, admin_user_id=test_platform_admin.id, platform_id=99999, assigned_by_user_id=test_super_admin.id, ) assert "Platform not found" in str(exc.value) def test_assign_admin_already_assigned( self, db, test_platform_admin, test_platform, test_super_admin ): """Test assigning already assigned admin raises error.""" service = AdminPlatformService() # First assignment service.assign_admin_to_platform( db=db, admin_user_id=test_platform_admin.id, platform_id=test_platform.id, assigned_by_user_id=test_super_admin.id, ) db.commit() # Try to assign again with pytest.raises(AdminOperationException) as exc: service.assign_admin_to_platform( db=db, admin_user_id=test_platform_admin.id, platform_id=test_platform.id, assigned_by_user_id=test_super_admin.id, ) assert "already assigned" in str(exc.value) def test_reactivate_inactive_assignment( self, db, test_platform_admin, test_platform, test_super_admin ): """Test reactivating an inactive assignment.""" from models.database.admin_platform import AdminPlatform service = AdminPlatformService() # Create inactive assignment directly assignment = AdminPlatform( user_id=test_platform_admin.id, platform_id=test_platform.id, is_active=False, assigned_by_user_id=test_super_admin.id, ) db.add(assignment) db.commit() # Assign again - should reactivate result = service.assign_admin_to_platform( db=db, admin_user_id=test_platform_admin.id, platform_id=test_platform.id, assigned_by_user_id=test_super_admin.id, ) assert result.is_active is True @pytest.mark.unit @pytest.mark.admin class TestAdminPlatformServiceRemove: """Test AdminPlatformService.remove_admin_from_platform.""" def test_remove_admin_from_platform_success( self, db, test_platform_admin, test_platform, test_super_admin ): """Test successfully removing an admin from a platform.""" from models.database.admin_platform import AdminPlatform service = AdminPlatformService() # Create assignment first assignment = AdminPlatform( user_id=test_platform_admin.id, platform_id=test_platform.id, is_active=True, assigned_by_user_id=test_super_admin.id, ) db.add(assignment) db.commit() # Remove service.remove_admin_from_platform( db=db, admin_user_id=test_platform_admin.id, platform_id=test_platform.id, removed_by_user_id=test_super_admin.id, ) db.commit() db.refresh(assignment) assert assignment.is_active is False def test_remove_admin_not_assigned( self, db, test_platform_admin, test_platform, test_super_admin ): """Test removing non-existent assignment raises error.""" service = AdminPlatformService() with pytest.raises(ValidationException) as exc: service.remove_admin_from_platform( db=db, admin_user_id=test_platform_admin.id, platform_id=test_platform.id, removed_by_user_id=test_super_admin.id, ) assert "not assigned" in str(exc.value) @pytest.mark.unit @pytest.mark.admin class TestAdminPlatformServiceQueries: """Test AdminPlatformService query methods.""" def test_get_platforms_for_admin( self, db, test_platform_admin, test_platform, another_platform, test_super_admin ): """Test getting platforms for an admin.""" from models.database.admin_platform import AdminPlatform service = AdminPlatformService() # Create assignments for platform in [test_platform, another_platform]: assignment = AdminPlatform( user_id=test_platform_admin.id, platform_id=platform.id, is_active=True, assigned_by_user_id=test_super_admin.id, ) db.add(assignment) db.commit() platforms = service.get_platforms_for_admin(db, test_platform_admin.id) assert len(platforms) == 2 platform_ids = [p.id for p in platforms] assert test_platform.id in platform_ids assert another_platform.id in platform_ids def test_get_platforms_for_admin_no_assignments(self, db, test_platform_admin): """Test getting platforms when no assignments exist.""" service = AdminPlatformService() platforms = service.get_platforms_for_admin(db, test_platform_admin.id) assert platforms == [] def test_get_admins_for_platform( self, db, test_platform_admin, test_platform, test_super_admin, auth_manager ): """Test getting admins for a platform.""" from models.database.admin_platform import AdminPlatform from models.database.user import User service = AdminPlatformService() # Create another platform admin another_admin = User( email="another_padmin@example.com", username="another_padmin", hashed_password=auth_manager.hash_password("pass"), role="admin", is_active=True, is_super_admin=False, ) db.add(another_admin) db.flush() # Create assignments for both admins for admin in [test_platform_admin, another_admin]: assignment = AdminPlatform( user_id=admin.id, platform_id=test_platform.id, is_active=True, assigned_by_user_id=test_super_admin.id, ) db.add(assignment) db.commit() admins = service.get_admins_for_platform(db, test_platform.id) assert len(admins) == 2 admin_ids = [a.id for a in admins] assert test_platform_admin.id in admin_ids assert another_admin.id in admin_ids def test_get_admin_assignments( self, db, test_platform_admin, test_platform, another_platform, test_super_admin ): """Test getting admin assignments with platform details.""" from models.database.admin_platform import AdminPlatform service = AdminPlatformService() # Create assignments for platform in [test_platform, another_platform]: assignment = AdminPlatform( user_id=test_platform_admin.id, platform_id=platform.id, is_active=True, assigned_by_user_id=test_super_admin.id, ) db.add(assignment) db.commit() assignments = service.get_admin_assignments(db, test_platform_admin.id) assert len(assignments) == 2 # Verify platform relationship is loaded for assignment in assignments: assert assignment.platform is not None assert assignment.platform.code is not None @pytest.mark.unit @pytest.mark.admin class TestAdminPlatformServiceSuperAdmin: """Test AdminPlatformService super admin operations.""" def test_toggle_super_admin_promote( self, db, test_platform_admin, test_super_admin ): """Test promoting admin to super admin.""" service = AdminPlatformService() result = service.toggle_super_admin( db=db, user_id=test_platform_admin.id, is_super_admin=True, current_admin_id=test_super_admin.id, ) db.commit() assert result.is_super_admin is True def test_toggle_super_admin_demote( self, db, test_super_admin, auth_manager ): """Test demoting super admin to platform admin.""" from models.database.user import User service = AdminPlatformService() # Create another super admin to demote another_super = User( email="another_super@example.com", username="another_super", hashed_password=auth_manager.hash_password("pass"), role="admin", is_active=True, is_super_admin=True, ) db.add(another_super) db.commit() result = service.toggle_super_admin( db=db, user_id=another_super.id, is_super_admin=False, current_admin_id=test_super_admin.id, ) db.commit() assert result.is_super_admin is False def test_toggle_super_admin_cannot_demote_self(self, db, test_super_admin): """Test that super admin cannot demote themselves.""" service = AdminPlatformService() with pytest.raises(CannotModifySelfException): service.toggle_super_admin( db=db, user_id=test_super_admin.id, is_super_admin=False, current_admin_id=test_super_admin.id, ) def test_toggle_super_admin_user_not_found(self, db, test_super_admin): """Test toggling non-existent user raises error.""" service = AdminPlatformService() with pytest.raises(ValidationException) as exc: service.toggle_super_admin( db=db, user_id=99999, is_super_admin=True, current_admin_id=test_super_admin.id, ) assert "User not found" in str(exc.value) def test_toggle_super_admin_not_admin( self, db, test_vendor_user, test_super_admin ): """Test toggling non-admin user raises error.""" service = AdminPlatformService() with pytest.raises(ValidationException) as exc: service.toggle_super_admin( db=db, user_id=test_vendor_user.id, is_super_admin=True, current_admin_id=test_super_admin.id, ) assert "must be an admin" in str(exc.value) @pytest.mark.unit @pytest.mark.admin class TestAdminPlatformServiceCreatePlatformAdmin: """Test AdminPlatformService.create_platform_admin.""" def test_create_platform_admin_success( self, db, test_platform, another_platform, test_super_admin ): """Test creating a new platform admin with assignments.""" service = AdminPlatformService() user, assignments = service.create_platform_admin( db=db, email="new_padmin@example.com", username="new_padmin", password="securepass123", platform_ids=[test_platform.id, another_platform.id], created_by_user_id=test_super_admin.id, first_name="New", last_name="Admin", ) db.commit() assert user is not None assert user.email == "new_padmin@example.com" assert user.username == "new_padmin" assert user.role == "admin" assert user.is_super_admin is False assert user.first_name == "New" assert user.last_name == "Admin" assert len(assignments) == 2 def test_create_platform_admin_duplicate_email( self, db, test_platform, test_super_admin, test_platform_admin ): """Test creating platform admin with duplicate email fails.""" service = AdminPlatformService() with pytest.raises(ValidationException) as exc: service.create_platform_admin( db=db, email=test_platform_admin.email, # Duplicate username="unique_username", password="securepass123", platform_ids=[test_platform.id], created_by_user_id=test_super_admin.id, ) assert "Email already exists" in str(exc.value) def test_create_platform_admin_duplicate_username( self, db, test_platform, test_super_admin, test_platform_admin ): """Test creating platform admin with duplicate username fails.""" service = AdminPlatformService() with pytest.raises(ValidationException) as exc: service.create_platform_admin( db=db, email="unique@example.com", username=test_platform_admin.username, # Duplicate password="securepass123", platform_ids=[test_platform.id], created_by_user_id=test_super_admin.id, ) assert "Username already exists" in str(exc.value)