""" Tests for User model - Task 1 validation """ import uuid import pytest import pytest_asyncio from sqlalchemy import select, text from sqlalchemy.ext.asyncio import AsyncSession from database.models import User, PlanType class TestUserModelFields: """Test User model has all required fields (AC1)""" @pytest.mark.asyncio async def test_user_has_tier_field_with_default_free( self, async_session: AsyncSession ): """AC1: User should have tier field with default 'free'""" user = User( email="test@example.com", name="Test User", hashed_password="hashed_abc123", ) async_session.add(user) await async_session.commit() assert user.tier == "free", "Default tier should be 'free'" @pytest.mark.asyncio async def test_user_tier_can_be_pro(self, async_session: AsyncSession): """AC1: User tier can be set to 'pro'""" user = User( email="pro@example.com", name="Pro User", hashed_password="hashed_abc123", tier="pro", ) async_session.add(user) await async_session.commit() assert user.tier == "pro" @pytest.mark.asyncio async def test_user_has_daily_translation_count_default_zero( self, async_session: AsyncSession ): """AC1: User should have daily_translation_count with default 0""" user = User( email="daily@example.com", name="Daily User", hashed_password="hashed_abc123", ) async_session.add(user) await async_session.commit() assert user.daily_translation_count == 0 @pytest.mark.asyncio async def test_user_has_hashed_password_field(self, async_session: AsyncSession): """AC1: User should have hashed_password field (renamed from password_hash)""" user = User( email="hash@example.com", name="Hash User", hashed_password="hashed_password_value", ) async_session.add(user) await async_session.commit() assert hasattr(user, "hashed_password") assert user.hashed_password == "hashed_password_value" @pytest.mark.asyncio async def test_user_has_uuid_id(self, async_session: AsyncSession): """AC1: User id should be UUID type""" user = User( email="uuid@example.com", name="UUID User", hashed_password="hashed_abc123", ) async_session.add(user) await async_session.commit() assert user.id is not None uuid.UUID(user.id) @pytest.mark.asyncio async def test_user_has_all_base_fields(self, async_session: AsyncSession): """AC1: User should have all required base fields""" user = User( email="base@example.com", name="Base User", hashed_password="hashed_abc123", ) async_session.add(user) await async_session.commit() assert user.email == "base@example.com" assert user.name == "Base User" assert user.created_at is not None assert user.updated_at is not None @pytest.mark.asyncio async def test_user_keeps_deprecated_plan_field_for_compatibility( self, async_session: AsyncSession ): """Task 1.4: Keep existing plan field for backward compatibility""" user = User( email="compat@example.com", name="Compat User", hashed_password="hashed_abc123", ) async_session.add(user) await async_session.commit() assert hasattr(user, "plan"), ( "plan field should still exist for backward compatibility" ) class TestUserModelAsyncOperations: """Test async database operations (AC2)""" @pytest.mark.asyncio async def test_create_user_async(self, async_session: AsyncSession): """AC2: Should be able to create user with async session""" user = User( email="async_create@example.com", name="Async Create", hashed_password="hashed_abc123", ) async_session.add(user) await async_session.commit() result = await async_session.execute( select(User).where(User.email == "async_create@example.com") ) found_user = result.scalar_one() assert found_user.email == "async_create@example.com" @pytest.mark.asyncio async def test_read_user_async(self, async_session: AsyncSession): """AC2: Should be able to read user with async session""" user = User( email="async_read@example.com", name="Async Read", hashed_password="hashed_abc123", ) async_session.add(user) await async_session.commit() result = await async_session.execute( select(User).where(User.email == "async_read@example.com") ) found_user = result.scalar_one() assert found_user.name == "Async Read" @pytest.mark.asyncio async def test_update_user_async(self, async_session: AsyncSession): """AC2: Should be able to update user with async session""" user = User( email="async_update@example.com", name="Async Update", hashed_password="hashed_abc123", ) async_session.add(user) await async_session.commit() user.tier = "pro" user.daily_translation_count = 5 await async_session.commit() result = await async_session.execute( select(User).where(User.email == "async_update@example.com") ) updated_user = result.scalar_one() assert updated_user.tier == "pro" assert updated_user.daily_translation_count == 5 @pytest.mark.asyncio async def test_delete_user_async(self, async_session: AsyncSession): """AC2: Should be able to delete user with async session""" user = User( email="async_delete@example.com", name="Async Delete", hashed_password="hashed_abc123", ) async_session.add(user) await async_session.commit() await async_session.delete(user) await async_session.commit() result = await async_session.execute( select(User).where(User.email == "async_delete@example.com") ) assert result.scalar_one_or_none() is None