import pytest from unittest.mock import MagicMock, patch from app.services.auth_service import AuthService from app.schemas import LoginSchema from app.exception import AuthException from werkzeug.security import generate_password_hash from app.models.entities import UserEntity from app.schemas.response import LoginResponseSchema from app.mapper import UserMapper @pytest.fixture def mock_user_repository(): return MagicMock() @pytest.fixture def auth_service(mock_user_repository): return AuthService(userRepository=mock_user_repository) @pytest.fixture def dummy_user_entity(): # Create a UserEntity instance with natural-looking data return UserEntity( id="6507a32a1f3b5e2dc8a45bf9", email="budi@mail.com", password=generate_password_hash("rahasia123"), name="Budi Santoso", locale="id-ID", ) @pytest.fixture def dummy_user_response(): # Create a mock response with natural-looking data return MagicMock( id="6507a32a1f3b5e2dc8a45bf9", email="budi@mail.com", name="Budi Santoso" ) # --- verify_google_id_token tests --- @patch("app.services.auth_service.id_token.verify_oauth2_token") def test_verify_google_existing_user( mock_verify, auth_service, mock_user_repository, dummy_user_entity, dummy_user_response, ): # Simulate valid token mock_verify.return_value = { "sub": "108762374589123456789", "email": "budi@mail.com", } mock_user_repository.get_by_google_id.return_value = dummy_user_entity # Setup the mapper to return our expected response with patch( "app.services.auth_service.UserMapper.user_entity_to_response" ) as mock_mapper: mock_mapper.return_value = dummy_user_response user = auth_service.verify_google_id_token("valid_token_string") assert user == dummy_user_response mock_user_repository.get_by_google_id.assert_called_once_with( "108762374589123456789" ) mock_mapper.assert_called_once_with(dummy_user_entity) @patch("app.services.auth_service.id_token.verify_oauth2_token") def test_verify_google_new_user( mock_verify, auth_service, mock_user_repository, dummy_user_entity, dummy_user_response, ): # Setup the Google payload with natural data google_payload = { "sub": "117239875612345678901", "email": "dewi@mail.com", "name": "Dewi Sartika", } mock_verify.return_value = google_payload # Setup repository responses mock_user_repository.get_by_google_id.return_value = None mock_user_repository.insert_user.return_value = "65081fe3ab234cdef9876543" mock_user_repository.get_user_by_id.return_value = dummy_user_entity # Setup mappers with patch( "app.services.auth_service.UserMapper.from_google_payload" ) as mock_from_google: with patch( "app.services.auth_service.UserMapper.user_entity_to_response" ) as mock_to_response: # Configure the mocks mock_from_google.return_value = dummy_user_entity mock_to_response.return_value = dummy_user_response # Call the method user = auth_service.verify_google_id_token("google_token_string") # Assertions assert user == dummy_user_response mock_user_repository.get_by_google_id.assert_called_once_with( "117239875612345678901" ) mock_from_google.assert_called_once_with( "117239875612345678901", "dewi@mail.com", google_payload ) mock_user_repository.insert_user.assert_called_once_with( user_data=dummy_user_entity ) mock_user_repository.get_user_by_id.assert_called_once_with( user_id="65081fe3ab234cdef9876543" ) mock_to_response.assert_called_once_with(dummy_user_entity) @patch("app.services.auth_service.id_token.verify_oauth2_token") def test_verify_google_email_mismatch( mock_verify, auth_service, mock_user_repository, dummy_user_entity ): # Setup mismatched email scenario with natural data mock_verify.return_value = { "sub": "108762374589123456789", "email": "dewi@mail.com", } dummy_user_entity.email = "budi@mail.com" mock_user_repository.get_by_google_id.return_value = dummy_user_entity # Test should raise exception with pytest.raises(AuthException, match="Email not match"): auth_service.verify_google_id_token("token_string") @patch("app.services.auth_service.id_token.verify_oauth2_token") def test_verify_google_invalid_token(mock_verify, auth_service): # Setup token verification failure mock_verify.side_effect = ValueError("Token tidak valid") # Test should raise exception with pytest.raises(Exception): auth_service.verify_google_id_token("invalid_token_string") # --- login tests --- def test_login_success( auth_service, mock_user_repository, dummy_user_entity, dummy_user_response ): # Setup repository mock_user_repository.get_user_by_email.return_value = dummy_user_entity # Setup mapper with patch( "app.services.auth_service.UserMapper.user_entity_to_response" ) as mock_mapper: mock_mapper.return_value = dummy_user_response # Call login with natural data schema = LoginSchema(email="budi@mail.com", password="rahasia123") user = auth_service.login(schema) # Assertions assert user == dummy_user_response mock_user_repository.get_user_by_email.assert_called_once_with("budi@mail.com") # Verify that password is set to None assert dummy_user_entity.password is None mock_mapper.assert_called_once_with(dummy_user_entity) def test_login_wrong_password(auth_service, mock_user_repository, dummy_user_entity): # Setup repository with correct user mock_user_repository.get_user_by_email.return_value = dummy_user_entity # Login with wrong password schema = LoginSchema(email="budi@mail.com", password="password_salah") user = auth_service.login(schema) # Assertions assert user is None mock_user_repository.get_user_by_email.assert_called_once_with("budi@mail.com") def test_login_user_not_found(auth_service, mock_user_repository): # Setup repository to return no user mock_user_repository.get_user_by_email.return_value = None # Login with unknown email schema = LoginSchema(email="tidak_ada@mail.com", password="rahasia123") user = auth_service.login(schema) # Assertions assert user is None mock_user_repository.get_user_by_email.assert_called_once_with("tidak_ada@mail.com")