# tests/persistence/test_sqlite_user.py from datetime import datetime import pytest from myauth.exceptions import UserAlreadyExistsError, UserNotFoundError from myauth.models.user import UserCreate, UserUpdate from myauth.persistence.sqlite import SQLiteUserRepository def test_i_can_create_and_retrieve_user_by_email(user_repository: SQLiteUserRepository, test_user_data_create: UserCreate, test_user_hashed_password: str): """Verifies user creation and successful retrieval by email.""" # 1. Create User created_user = user_repository.create_user( user_data=test_user_data_create, hashed_password=test_user_hashed_password ) # Assertions on creation assert created_user is not None assert created_user.email == test_user_data_create.email assert created_user.hashed_password == test_user_hashed_password assert created_user.is_active is True assert created_user.is_verified is False assert created_user.id is not None assert isinstance(created_user.created_at, datetime) # 2. Retrieve User retrieved_user = user_repository.get_user_by_email(test_user_data_create.email) # Assertions on retrieval assert retrieved_user is not None assert retrieved_user.id == created_user.id assert retrieved_user.username == "TestUser" def test_i_can_retrieve_user_by_id(user_repository: SQLiteUserRepository, test_user_data_create: UserCreate, test_user_hashed_password: str): """Verifies user retrieval by unique ID.""" created_user = user_repository.create_user(test_user_data_create, test_user_hashed_password) retrieved_user = user_repository.get_user_by_id(created_user.id) assert retrieved_user is not None assert retrieved_user.email == created_user.email def test_i_cannot_create_user_if_email_exists(user_repository: SQLiteUserRepository, test_user_data_create: UserCreate, test_user_hashed_password: str): """Ensures that creating a user with an existing email raises UserAlreadyExistsError.""" # First creation should succeed user_repository.create_user(test_user_data_create, test_user_hashed_password) # Second creation with same email should fail with pytest.raises(UserAlreadyExistsError): user_repository.create_user(test_user_data_create, test_user_hashed_password) def test_i_can_check_if_email_exists(user_repository: SQLiteUserRepository, test_user_data_create: UserCreate, test_user_hashed_password: str): """Verifies the email_exists method returns correct boolean results.""" email = test_user_data_create.email non_existent_email = "non.existent@example.com" # 1. Check before creation (Should be False) assert user_repository.email_exists(email) is False user_repository.create_user(test_user_data_create, test_user_hashed_password) # 2. Check after creation (Should be True) assert user_repository.email_exists(email) is True # 3. Check for another non-existent email assert user_repository.email_exists(non_existent_email) is False def test_i_can_update_username_and_roles(user_repository: SQLiteUserRepository, test_user_data_create: UserCreate, test_user_hashed_password: str): """Tests partial update of user fields (username and roles).""" created_user = user_repository.create_user(test_user_data_create, test_user_hashed_password) updates = UserUpdate(username="NewUsername", roles=["admin", "staff"]) updated_user = user_repository.update_user(created_user.id, updates) assert updated_user.username == "NewUsername" assert updated_user.roles == ["admin", "staff"] # Check that unrelated fields remain the same assert updated_user.email == created_user.email # Check that update timestamp changed assert updated_user.updated_at > created_user.updated_at assert updated_user.is_verified == created_user.is_verified def test_i_can_update_is_active_status(user_repository: SQLiteUserRepository, test_user_data_create: UserCreate, test_user_hashed_password: str): """Tests the specific update of the 'is_active' status.""" created_user = user_repository.create_user(test_user_data_create, test_user_hashed_password) # Deactivate updates_deactivate = UserUpdate(is_active=False) deactivated_user = user_repository.update_user(created_user.id, updates_deactivate) assert deactivated_user.is_active is False # Reactivate updates_activate = UserUpdate(is_active=True) reactivated_user = user_repository.update_user(created_user.id, updates_activate) assert reactivated_user.is_active is True def test_i_cannot_update_non_existent_user(user_repository: SQLiteUserRepository): """Ensures that updating a user with an unknown ID raises UserNotFoundError.""" non_existent_id = "unknown_id_123" updates = UserUpdate(username="Phantom") with pytest.raises(UserNotFoundError): user_repository.update_user(non_existent_id, updates) def test_i_can_delete_user(user_repository: SQLiteUserRepository, test_user_data_create: UserCreate, test_user_hashed_password: str): """Verifies user deletion and subsequent failure to retrieve.""" created_user = user_repository.create_user(test_user_data_create, test_user_hashed_password) # 1. Delete the user was_deleted = user_repository.delete_user(created_user.id) assert was_deleted is True # 2. Verify deletion by attempting retrieval retrieved_user = user_repository.get_user_by_id(created_user.id) assert retrieved_user is None # 3. Verify attempting to delete again returns False was_deleted_again = user_repository.delete_user(created_user.id) assert was_deleted_again is False def test_i_cannot_retrieve_non_existent_user_by_email(user_repository: SQLiteUserRepository): """Ensures retrieval by email returns None for non-existent email.""" retrieved_user = user_repository.get_user_by_email("ghost@example.com") assert retrieved_user is None def test_i_can_list_users_with_pagination(user_repository: SQLiteUserRepository, test_user_hashed_password: str): """Verifies that list_users returns paginated results correctly.""" # Create multiple users for i in range(5): user_data = UserCreate( email=f"user{i}@example.com", username=f"User{i}", password="#Password123", roles=["user"], user_settings={} ) user_repository.create_user(user_data, test_user_hashed_password) # Test: Get first 3 users users_page1 = user_repository.list_users(skip=0, limit=3) assert len(users_page1) == 3 # Test: Get next 2 users users_page2 = user_repository.list_users(skip=3, limit=3) assert len(users_page2) == 2 # Test: Verify no duplicates between pages page1_ids = {user.id for user in users_page1} page2_ids = {user.id for user in users_page2} assert len(page1_ids.intersection(page2_ids)) == 0 def test_i_can_list_users_with_default_pagination(user_repository: SQLiteUserRepository, test_user_data_create: UserCreate, test_user_hashed_password: str): """Verifies that list_users works with default parameters.""" # Create 2 users user_repository.create_user(test_user_data_create, test_user_hashed_password) user_data2 = UserCreate( email="user2@example.com", username="User2", password="#Password123", roles=["user"], user_settings={} ) user_repository.create_user(user_data2, test_user_hashed_password) # Test: Default parameters (skip=0, limit=100) users = user_repository.list_users() assert len(users) == 2 assert all(isinstance(user.created_at, datetime) for user in users) def test_i_get_empty_list_when_no_users_exist(user_repository: SQLiteUserRepository): """Verifies that list_users returns an empty list when no users exist.""" users = user_repository.list_users() assert users == [] assert isinstance(users, list) def test_i_can_skip_beyond_available_users(user_repository: SQLiteUserRepository, test_user_data_create: UserCreate, test_user_hashed_password: str): """Verifies that skipping beyond available users returns an empty list.""" user_repository.create_user(test_user_data_create, test_user_hashed_password) # Skip beyond the only user users = user_repository.list_users(skip=10, limit=10) assert users == [] def test_i_can_count_users(user_repository: SQLiteUserRepository, test_user_hashed_password: str): """Verifies that count_users returns the correct number of users.""" # Initial count should be 0 assert user_repository.count_users() == 0 # Create first user user_data1 = UserCreate( email="user1@example.com", username="User1", password="#Password123", roles=["user"], user_settings={} ) user_repository.create_user(user_data1, test_user_hashed_password) assert user_repository.count_users() == 1 # Create second user user_data2 = UserCreate( email="user2@example.com", username="User2", password="#Password123", roles=["user"], user_settings={} ) user_repository.create_user(user_data2, test_user_hashed_password) assert user_repository.count_users() == 2 def test_i_get_zero_count_when_no_users_exist(user_repository: SQLiteUserRepository): """Verifies that count_users returns 0 when the database is empty.""" count = user_repository.count_users() assert count == 0 assert isinstance(count, int) def test_list_users_returns_correct_user_structure(user_repository: SQLiteUserRepository, test_user_data_create: UserCreate, test_user_hashed_password: str): """Verifies that list_users returns UserInDB objects with all fields.""" user_repository.create_user(test_user_data_create, test_user_hashed_password) users = user_repository.list_users() assert len(users) == 1 user = users[0] # Verify all fields are present and correct type assert user.id is not None assert user.email == test_user_data_create.email assert user.username == test_user_data_create.username assert user.hashed_password == test_user_hashed_password assert isinstance(user.roles, list) assert isinstance(user.user_settings, dict) assert isinstance(user.is_verified, bool) assert isinstance(user.is_active, bool) assert isinstance(user.created_at, datetime) assert isinstance(user.updated_at, datetime)