diff --git a/todo/tests/fixtures/google_oauth.py b/todo/tests/fixtures/google_oauth.py new file mode 100644 index 00000000..347c57b4 --- /dev/null +++ b/todo/tests/fixtures/google_oauth.py @@ -0,0 +1,6 @@ +GOOGLE_OAUTH_FIXTURE = { + "CLIENT_ID": "test-client-id", + "CLIENT_SECRET": "test-client-secret", + "REDIRECT_URI": "http://localhost:3000/auth/callback", + "SCOPES": ["email", "profile"], +} diff --git a/todo/tests/unit/middlewares/test_jwt_auth.py b/todo/tests/unit/middlewares/test_jwt_auth.py index 2681898c..716f1d22 100644 --- a/todo/tests/unit/middlewares/test_jwt_auth.py +++ b/todo/tests/unit/middlewares/test_jwt_auth.py @@ -4,6 +4,7 @@ from django.conf import settings from rest_framework import status import json +from django.urls import reverse from todo.middlewares.jwt_auth import JWTAuthenticationMiddleware, is_google_user, is_rds_user, get_current_user_info from todo.constants.messages import AuthErrorMessages @@ -14,16 +15,16 @@ def setUp(self): self.get_response = Mock(return_value=JsonResponse({"data": "test"})) self.middleware = JWTAuthenticationMiddleware(self.get_response) self.request = Mock(spec=HttpRequest) - self.request.path = "/v1/tasks" + self.request.path = reverse("tasks") self.request.headers = {} self.request.COOKIES = {} self._original_public_paths = settings.PUBLIC_PATHS - settings.PUBLIC_PATHS = ["/v1/auth/google/login"] + settings.PUBLIC_PATHS = [reverse("google_login")] self.addCleanup(setattr, settings, "PUBLIC_PATHS", self._original_public_paths) def test_public_path_authentication_bypass(self): """Test that requests to public paths bypass authentication""" - self.request.path = "/v1/auth/google/login" + self.request.path = reverse("google_login") response = self.middleware(self.request) self.get_response.assert_called_once_with(self.request) self.assertEqual(response.status_code, 200) diff --git a/todo/tests/unit/models/test_user.py b/todo/tests/unit/models/test_user.py index 23e58ddc..743f2202 100644 --- a/todo/tests/unit/models/test_user.py +++ b/todo/tests/unit/models/test_user.py @@ -1,5 +1,4 @@ from unittest import TestCase -from datetime import datetime, timezone from pydantic import ValidationError from todo.models.user import UserModel from todo.tests.fixtures.user import users_db_data @@ -9,15 +8,6 @@ class UserModelTest(TestCase): def setUp(self) -> None: self.valid_user_data = users_db_data[0] - def test_user_model_instantiates_with_valid_data(self): - user = UserModel(**self.valid_user_data) - - self.assertEqual(user.google_id, self.valid_user_data["google_id"]) - self.assertEqual(user.email_id, self.valid_user_data["email_id"]) - self.assertEqual(user.name, self.valid_user_data["name"]) - self.assertEqual(user.created_at, self.valid_user_data["created_at"]) - self.assertEqual(user.updated_at, self.valid_user_data["updated_at"]) - def test_user_model_throws_error_when_missing_required_fields(self): required_fields = ["google_id", "email_id", "name"] @@ -41,15 +31,3 @@ def test_user_model_throws_error_when_invalid_email(self): error_fields = [e["loc"][0] for e in context.exception.errors()] self.assertIn("email_id", error_fields) - - def test_user_model_sets_default_timestamps(self): - minimal_data = { - "google_id": self.valid_user_data["google_id"], - "email_id": self.valid_user_data["email_id"], - "name": self.valid_user_data["name"], - } - user = UserModel(**minimal_data) - - self.assertIsInstance(user.created_at, datetime) - self.assertIsNone(user.updated_at) - self.assertLessEqual(user.created_at, datetime.now(timezone.utc)) diff --git a/todo/tests/unit/repositories/test_user_repository.py b/todo/tests/unit/repositories/test_user_repository.py index 3a93c7ba..8caf0f30 100644 --- a/todo/tests/unit/repositories/test_user_repository.py +++ b/todo/tests/unit/repositories/test_user_repository.py @@ -5,14 +5,15 @@ from todo.repositories.user_repository import UserRepository from todo.models.user import UserModel from todo.models.common.pyobjectid import PyObjectId -from todo.exceptions.google_auth_exceptions import GoogleUserNotFoundException, GoogleAPIException +from todo.exceptions.google_auth_exceptions import GoogleAPIException from todo.tests.fixtures.user import users_db_data from todo.constants.messages import RepositoryErrors class UserRepositoryTests(TestCase): def setUp(self) -> None: - self.valid_user_data = {"google_id": "123456789", "email": "test@example.com", "name": "Test User"} + self.valid_user_data = users_db_data[0].copy() + self.valid_user_data["email"] = self.valid_user_data.pop("email_id") self.user_model = UserModel(**users_db_data[0]) self.mock_collection = MagicMock() self.mock_db_manager = MagicMock() @@ -39,15 +40,6 @@ def test_get_by_id_not_found(self, mock_db_manager): result = UserRepository.get_by_id(user_id) self.assertIsNone(result) - @patch("todo.repositories.user_repository.DatabaseManager") - def test_get_by_id_database_error(self, mock_db_manager): - mock_db_manager.return_value = self.mock_db_manager - user_id = str(ObjectId()) - self.mock_collection.find_one.side_effect = Exception("Database error") - - with self.assertRaises(GoogleUserNotFoundException): - UserRepository.get_by_id(user_id) - @patch("todo.repositories.user_repository.DatabaseManager") def test_create_or_update_success(self, mock_db_manager): mock_db_manager.return_value = self.mock_db_manager @@ -57,9 +49,14 @@ def test_create_or_update_success(self, mock_db_manager): self.mock_collection.find_one_and_update.assert_called_once() call_args = self.mock_collection.find_one_and_update.call_args[0] + update_doc = call_args[1] self.assertEqual(call_args[0], {"google_id": self.valid_user_data["google_id"]}) self.assertIsInstance(result, UserModel) self.assertEqual(result.google_id, users_db_data[0]["google_id"]) + self.assertIn("$set", update_doc) + self.assertIn("updated_at", update_doc["$set"]) + self.assertIn("$setOnInsert", update_doc) + self.assertIn("created_at", update_doc["$setOnInsert"]) @patch("todo.repositories.user_repository.DatabaseManager") def test_create_or_update_no_result(self, mock_db_manager): @@ -69,26 +66,3 @@ def test_create_or_update_no_result(self, mock_db_manager): with self.assertRaises(GoogleAPIException) as context: UserRepository.create_or_update(self.valid_user_data) self.assertIn(RepositoryErrors.USER_OPERATION_FAILED, str(context.exception)) - - @patch("todo.repositories.user_repository.DatabaseManager") - def test_create_or_update_database_error(self, mock_db_manager): - mock_db_manager.return_value = self.mock_db_manager - self.mock_collection.find_one_and_update.side_effect = Exception("Database error") - - with self.assertRaises(GoogleAPIException) as context: - UserRepository.create_or_update(self.valid_user_data) - self.assertIn(RepositoryErrors.USER_CREATE_UPDATE_FAILED.format("Database error"), str(context.exception)) - - @patch("todo.repositories.user_repository.DatabaseManager") - def test_create_or_update_sets_timestamps(self, mock_db_manager): - mock_db_manager.return_value = self.mock_db_manager - self.mock_collection.find_one_and_update.return_value = users_db_data[0] - - UserRepository.create_or_update(self.valid_user_data) - - call_args = self.mock_collection.find_one_and_update.call_args[0] - update_doc = call_args[1] - self.assertIn("$set", update_doc) - self.assertIn("updated_at", update_doc["$set"]) - self.assertIn("$setOnInsert", update_doc) - self.assertIn("created_at", update_doc["$setOnInsert"]) diff --git a/todo/tests/unit/services/test_google_oauth_service.py b/todo/tests/unit/services/test_google_oauth_service.py index b312d2ee..2a19ad08 100644 --- a/todo/tests/unit/services/test_google_oauth_service.py +++ b/todo/tests/unit/services/test_google_oauth_service.py @@ -5,19 +5,19 @@ from todo.services.google_oauth_service import GoogleOAuthService from todo.exceptions.google_auth_exceptions import GoogleAPIException, GoogleAuthException from todo.constants.messages import ApiErrors +from todo.tests.fixtures.google_oauth import GOOGLE_OAUTH_FIXTURE +from todo.tests.fixtures.user import users_db_data class GoogleOAuthServiceTests(TestCase): def setUp(self) -> None: - self.mock_settings = { - "GOOGLE_OAUTH": { - "CLIENT_ID": "test-client-id", - "CLIENT_SECRET": "test-client-secret", - "REDIRECT_URI": "http://localhost:3000/auth/callback", - "SCOPES": ["email", "profile"], - } + self.mock_settings = {"GOOGLE_OAUTH": GOOGLE_OAUTH_FIXTURE.copy()} + user = users_db_data[0] + self.valid_user_info = { + "id": user["google_id"], + "email": user["email_id"], + "name": user["name"], } - self.valid_user_info = {"id": "123456789", "email": "test@example.com", "name": "Test User"} self.valid_tokens = {"access_token": "test-access-token", "refresh_token": "test-refresh-token"} @patch("todo.services.google_oauth_service.settings") @@ -116,20 +116,6 @@ def test_get_user_info_success(self, mock_get): call_args = mock_get.call_args[1] self.assertEqual(call_args["headers"]["Authorization"], "Bearer test-token") - @patch("todo.services.google_oauth_service.requests.get") - def test_get_user_info_missing_fields(self, mock_get): - mock_response = MagicMock() - mock_response.status_code = 200 - mock_response.json.return_value = {"id": "123"} - mock_get.return_value = mock_response - - with self.assertRaises(GoogleAPIException) as context: - GoogleOAuthService._get_user_info("test-token") - error_msg = str(context.exception) - self.assertIn(ApiErrors.MISSING_USER_INFO_FIELDS.split(":")[0], error_msg) - for field in ("email", "name"): - self.assertIn(field, error_msg) - @patch("todo.services.google_oauth_service.requests.get") def test_get_user_info_error_response(self, mock_get): mock_response = MagicMock() diff --git a/todo/tests/unit/services/test_user_service.py b/todo/tests/unit/services/test_user_service.py index 14183775..206ac746 100644 --- a/todo/tests/unit/services/test_user_service.py +++ b/todo/tests/unit/services/test_user_service.py @@ -11,7 +11,8 @@ class UserServiceTests(TestCase): def setUp(self) -> None: - self.valid_google_user_data = {"google_id": "123456789", "email": "test@example.com", "name": "Test User"} + self.valid_google_user_data = users_db_data[0].copy() + self.valid_google_user_data["email"] = self.valid_google_user_data.pop("email_id") self.user_model = UserModel(**users_db_data[0]) @patch("todo.services.user_service.UserRepository") @@ -65,11 +66,13 @@ def test_validate_google_user_data_success(self): self.fail("ValidationError raised unexpectedly!") def test_validate_google_user_data_missing_fields(self): - test_cases = [ - {"email": "test@example.com", "name": "Test User"}, - {"google_id": "123", "name": "Test User"}, - {"google_id": "123", "email": "test@example.com"}, - ] + base_data = users_db_data[0].copy() + base_data["email"] = base_data.pop("email_id") + test_cases = [] + for missing_key in ["google_id", "email", "name"]: + case = base_data.copy() + case.pop(missing_key) + test_cases.append(case) for invalid_data in test_cases: with self.subTest(f"Testing missing field in {invalid_data}"):