81 lines
2.4 KiB
Python
81 lines
2.4 KiB
Python
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
|