import pytest from ai_platform.platform.application.admin_users import ( AdminUserAlreadyExists, AdminUserUseCases, ) class Repository: def __init__(self, *, existing: bool = False, conflict_on_create: bool = False) -> None: self.existing = existing self.conflict_on_create = conflict_on_create self.created: tuple[str, str] | None = None async def exists(self, email: str) -> bool: assert email == "admin@example.invalid" return self.existing async def create(self, email: str, password_hash: str) -> None: if self.conflict_on_create: raise AdminUserAlreadyExists self.created = (email, password_hash) class Transaction: def __init__(self) -> None: self.commits = 0 self.rollbacks = 0 async def commit(self) -> None: self.commits += 1 async def rollback(self) -> None: self.rollbacks += 1 def make_use_case(repository: Repository, transaction: Transaction) -> AdminUserUseCases: return AdminUserUseCases( repository=repository, hash_password=lambda password: f"hashed:{password}", commit=transaction.commit, rollback=transaction.rollback, ) async def test_create_normalizes_email_hashes_password_and_commits(): repository = Repository() transaction = Transaction() use_case = make_use_case(repository, transaction) await use_case.create(" Admin@Example.Invalid ", "test-password") assert repository.created == ("admin@example.invalid", "hashed:test-password") assert transaction.commits == 1 assert transaction.rollbacks == 0 async def test_existing_admin_is_rejected_without_mutation(): repository = Repository(existing=True) transaction = Transaction() use_case = make_use_case(repository, transaction) with pytest.raises(AdminUserAlreadyExists): await use_case.create("admin@example.invalid", "test-password") assert repository.created is None assert transaction.commits == 0 assert transaction.rollbacks == 0 async def test_concurrent_duplicate_admin_creation_rolls_back(): repository = Repository(conflict_on_create=True) transaction = Transaction() use_case = make_use_case(repository, transaction) with pytest.raises(AdminUserAlreadyExists): await use_case.create("admin@example.invalid", "test-password") assert transaction.commits == 0 assert transaction.rollbacks == 1