"""Юнит-тесты модели `ConferenceInvitee`: CHECK «ровно одна identity» и частичные UNIQUE-индексы (ADR-003, `docs/architecture/adr/003-conference-invitees.md`). """ import uuid import pytest from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.asyncio import AsyncSession from core.security import hash_password from models.conference import Conference from models.invitee import ConferenceInvitee from models.user import User from services.conference_ids import generate_number, generate_slug async def _make_user(session: AsyncSession) -> User: user = User( email=f"{uuid.uuid4()}@example.com", name_user="Invitee Tester", password_hash=await hash_password("password123"), email_verified=True, ) session.add(user) await session.flush() return user async def _make_conference( session: AsyncSession, *, owner_id: uuid.UUID | None = None ) -> Conference: conference = Conference( number=generate_number(), slug=generate_slug(), owner_id=owner_id, status="scheduled" ) session.add(conference) await session.flush() return conference async def test_neither_user_id_nor_email_violates_check(db_session: AsyncSession) -> None: conference = await _make_conference(db_session) db_session.add(ConferenceInvitee(conference_id=conference.id)) with pytest.raises(IntegrityError): await db_session.commit() async def test_both_user_id_and_email_violates_check(db_session: AsyncSession) -> None: conference = await _make_conference(db_session) invitee_user = await _make_user(db_session) await db_session.commit() db_session.add( ConferenceInvitee( conference_id=conference.id, user_id=invitee_user.id, email="x@example.com" ) ) with pytest.raises(IntegrityError): await db_session.commit() async def test_duplicate_user_id_on_same_conference_violates_unique( db_session: AsyncSession, ) -> None: conference = await _make_conference(db_session) invitee_user = await _make_user(db_session) db_session.add(ConferenceInvitee(conference_id=conference.id, user_id=invitee_user.id)) await db_session.commit() db_session.add(ConferenceInvitee(conference_id=conference.id, user_id=invitee_user.id)) with pytest.raises(IntegrityError): await db_session.commit() async def test_duplicate_email_case_insensitive_violates_unique(db_session: AsyncSession) -> None: conference = await _make_conference(db_session) unique_email = f"guest-{uuid.uuid4()}@example.com" db_session.add(ConferenceInvitee(conference_id=conference.id, email=unique_email)) await db_session.commit() db_session.add(ConferenceInvitee(conference_id=conference.id, email=unique_email.upper())) with pytest.raises(IntegrityError): await db_session.commit() async def test_same_email_on_different_conferences_is_allowed(db_session: AsyncSession) -> None: conference_a = await _make_conference(db_session) conference_b = await _make_conference(db_session) shared_email = f"shared-{uuid.uuid4()}@example.com" db_session.add(ConferenceInvitee(conference_id=conference_a.id, email=shared_email)) db_session.add(ConferenceInvitee(conference_id=conference_b.id, email=shared_email)) await db_session.commit() # не должно бросить — разные конференции