"""Tests for user services""" from apps.core.exceptions import NotFoundError from apps.user.services import ProfileService, UserService from django.contrib.auth import get_user_model from django.test import TestCase from faker import Faker from rest_framework_simplejwt.tokens import RefreshToken from .factories import ProfileFactory, UserFactory User = get_user_model() fake = Faker("ru_RU") class UserServiceTest(TestCase): """Tests for UserService""" def setUp(self): self.user = UserFactory.create_user() self.user_data = { "email": fake.unique.email(), "username": fake.unique.user_name(), "password": fake.password(length=12, special_chars=False), } def test_create_user_success(self): """Test successful user creation""" user = UserService.create_user(**self.user_data) self.assertIsInstance(user, User) self.assertEqual(user.email, self.user_data["email"]) self.assertEqual(user.username, self.user_data["username"]) self.assertTrue(user.check_password(self.user_data["password"])) self.assertFalse(user.is_verified) # Default value self.assertEqual(UserService.get_user_role(user), UserService.ROLE_USER) self.assertTrue(user.groups.filter(name=UserService.ROLE_USER).exists()) def test_create_user_with_extra_fields(self): """Test user creation with extra fields""" extra_data = self.user_data.copy() extra_data["email"] = fake.unique.email() extra_data["username"] = fake.unique.user_name() extra_data["phone"] = f"+7{fake.numerify('##########')}" extra_data["is_verified"] = True user = UserService.create_user(**extra_data) self.assertEqual(user.phone, extra_data["phone"]) self.assertTrue(user.is_verified) def test_create_user_with_admin_role(self): """Test admin role assignment on creation.""" user = UserService.create_user(role=UserService.ROLE_ADMIN, **self.user_data) self.assertTrue(user.is_staff) self.assertEqual(UserService.get_user_role(user), UserService.ROLE_ADMIN) self.assertTrue(user.groups.filter(name=UserService.ROLE_ADMIN).exists()) def test_create_user_with_profile_names(self): user = UserService.create_user( **self.user_data, first_name="Иван", middle_name="Иванович", last_name="Иванов", ) self.assertEqual(user.profile.first_name, "Иван") self.assertEqual(user.profile.middle_name, "Иванович") self.assertEqual(user.profile.last_name, "Иванов") def test_get_user_by_email_found(self): """Test getting user by existing email""" found_user = UserService.get_user_by_email(self.user.email) self.assertEqual(found_user, self.user) def test_get_user_by_email_not_found(self): """Test getting user by non-existing email raises NotFoundError""" nonexistent_email = fake.unique.email() with self.assertRaises(NotFoundError) as context: UserService.get_user_by_email(nonexistent_email) self.assertEqual(context.exception.code, "not_found") self.assertIn("email", context.exception.message) def test_get_user_by_email_or_none_not_found(self): """Test getting user by non-existing email returns None""" found_user = UserService.get_user_by_email_or_none(fake.unique.email()) self.assertIsNone(found_user) def test_get_user_by_id_found(self): """Test getting user by existing ID""" found_user = UserService.get_user_by_id(self.user.id) self.assertEqual(found_user, self.user) def test_get_user_by_id_not_found(self): """Test getting user by non-existing ID raises NotFoundError""" nonexistent_id = fake.pyint(min_value=900000, max_value=999999) with self.assertRaises(NotFoundError) as context: UserService.get_user_by_id(nonexistent_id) self.assertEqual(context.exception.code, "not_found") self.assertIn(str(nonexistent_id), context.exception.message) def test_get_user_by_id_or_none_not_found(self): """Test getting user by non-existing ID returns None""" found_user = UserService.get_user_by_id_or_none( fake.pyint(min_value=900000, max_value=999999) ) self.assertIsNone(found_user) def test_update_user_success(self): """Test successful user update""" new_data = { "username": fake.unique.user_name(), "phone": f"+7{fake.numerify('##########')}", } updated_user = UserService.update_user(self.user.id, **new_data) self.assertIsNotNone(updated_user) self.assertEqual(updated_user.username, new_data["username"]) self.assertEqual(updated_user.phone, new_data["phone"]) def test_update_user_not_found(self): """Test updating non-existing user raises NotFoundError""" nonexistent_id = fake.pyint(min_value=900000, max_value=999999) with self.assertRaises(NotFoundError): UserService.update_user(nonexistent_id, username=fake.user_name()) def test_update_managed_user_updates_role_and_profile(self): """Test admin update flow changes role and profile names.""" updated_user = UserService.update_managed_user( self.user.id, role=UserService.ROLE_ADMIN, first_name="Иван", middle_name="Иванович", last_name="Иванов", ) self.assertEqual( UserService.get_user_role(updated_user), UserService.ROLE_ADMIN ) self.assertTrue(updated_user.is_staff) self.assertEqual(updated_user.profile.first_name, "Иван") self.assertEqual(updated_user.profile.middle_name, "Иванович") self.assertEqual(updated_user.profile.last_name, "Иванов") def test_update_managed_user_updates_password(self): raw_password = fake.password(length=12, special_chars=False) updated_user = UserService.update_managed_user( self.user.id, password=raw_password, ) self.assertTrue(updated_user.check_password(raw_password)) def test_delete_user_success(self): """Test successful user deletion""" user_id = self.user.id UserService.delete_user(user_id) # Verify user is deleted with self.assertRaises(NotFoundError): UserService.get_user_by_id(user_id) def test_delete_user_not_found(self): """Test deleting non-existing user raises NotFoundError""" nonexistent_id = fake.pyint(min_value=900000, max_value=999999) with self.assertRaises(NotFoundError): UserService.delete_user(nonexistent_id) def test_deactivate_user_success(self): """Test soft deactivation of user.""" user = UserService.deactivate_user(self.user.id) self.assertFalse(user.is_active) def test_activate_user_success(self): """Test activation of user.""" self.user.is_active = False self.user.save(update_fields=["is_active"]) user = UserService.activate_user(self.user.id) self.assertTrue(user.is_active) def test_get_filtered_users_queryset_searches_by_profile_name(self): ProfileFactory.create_profile( user=self.user, first_name="Найден", middle_name="Тестович", last_name="Пользователь", ) queryset = UserService.get_filtered_users_queryset(search="Тестович") self.assertEqual(list(queryset.values_list("id", flat=True)), [self.user.id]) def test_get_filtered_users_queryset_orders_by_profile_field(self): first = UserFactory.create_user() second = UserFactory.create_user() ProfileFactory.create_profile(user=first, first_name="Борис") ProfileFactory.create_profile(user=second, first_name="Алексей") queryset = UserService.get_filtered_users_queryset(ordering="first_name") ids = list(queryset.values_list("id", flat=True)) self.assertLess(ids.index(second.id), ids.index(first.id)) def test_get_user_capabilities_for_admin(self): """Test admin capabilities set.""" admin = UserFactory.create_user(is_staff=True) capabilities = UserService.get_user_capabilities(admin) self.assertTrue(capabilities["can_manage_users"]) self.assertTrue(capabilities["can_refresh_dashboard"]) self.assertIn("exchange", capabilities["settings_sections"]) def test_get_user_capabilities_for_regular_user(self): """Test regular user capabilities set.""" capabilities = UserService.get_user_capabilities(self.user) self.assertFalse(capabilities["can_manage_users"]) self.assertFalse(capabilities["can_refresh_dashboard"]) self.assertEqual(capabilities["settings_sections"], []) def test_get_user_role_uses_admin_group(self): user = UserFactory.create_user(is_staff=False, is_superuser=False) admin_group = UserService.ensure_role_groups()[UserService.ROLE_ADMIN] user.groups.add(admin_group) self.assertEqual(UserService.get_user_role(user), UserService.ROLE_ADMIN) def test_assign_role_replaces_previous_role_group(self): user = UserFactory.create_user() UserService.assign_role(user, UserService.ROLE_ADMIN) self.assertTrue(user.groups.filter(name=UserService.ROLE_ADMIN).exists()) self.assertFalse(user.groups.filter(name=UserService.ROLE_USER).exists()) def test_assign_role_rejects_unknown_role(self): with self.assertRaisesMessage(ValueError, "Unsupported role: root"): UserService.assign_role(self.user, "root") def test_get_tokens_for_user(self): """Test JWT token generation""" tokens = UserService.get_tokens_for_user(self.user) self.assertIn("refresh", tokens) self.assertIn("access", tokens) self.assertIsInstance(tokens["refresh"], str) self.assertIsInstance(tokens["access"], str) # Verify tokens are valid refresh = RefreshToken(tokens["refresh"]) self.assertEqual(refresh["user_id"], self.user.id) def test_verify_email_success(self): """Test successful email verification""" self.user.is_verified = False self.user.save() user = UserService.verify_email(self.user.id) self.assertEqual(user.id, self.user.id) self.user.refresh_from_db() self.assertTrue(self.user.is_verified) def test_verify_email_not_found(self): """Test email verification for non-existing user raises NotFoundError""" nonexistent_id = fake.pyint(min_value=900000, max_value=999999) with self.assertRaises(NotFoundError): UserService.verify_email(nonexistent_id) class ProfileServiceTest(TestCase): """Tests for ProfileService""" def setUp(self): self.user = UserFactory.create_user() self.profile = ProfileFactory.create_profile(user=self.user) self.profile_data = { "first_name": fake.first_name(), "middle_name": fake.first_name(), "last_name": fake.last_name(), "bio": fake.text(max_nb_chars=200), "date_of_birth": str(fake.date_of_birth(minimum_age=18, maximum_age=80)), } def test_get_profile_by_user_id_found(self): """Test getting profile by existing user ID""" found_profile = ProfileService.get_profile_by_user_id(self.user.id) self.assertEqual(found_profile, self.profile) # Check that user is selected related self.assertIsNotNone(found_profile.user) def test_get_profile_by_user_id_not_found(self): """Test getting profile by non-existing user ID raises NotFoundError""" nonexistent_id = fake.pyint(min_value=900000, max_value=999999) with self.assertRaises(NotFoundError) as context: ProfileService.get_profile_by_user_id(nonexistent_id) self.assertEqual(context.exception.code, "not_found") def test_get_profile_by_user_id_or_none_not_found(self): """Test getting profile by non-existing user ID returns None""" nonexistent_id = fake.pyint(min_value=900000, max_value=999999) found_profile = ProfileService.get_profile_by_user_id_or_none(nonexistent_id) self.assertIsNone(found_profile) def test_update_profile_success(self): """Test successful profile update""" updated_profile = ProfileService.update_profile( self.user.id, **self.profile_data ) self.assertIsNotNone(updated_profile) self.assertEqual(updated_profile.first_name, self.profile_data["first_name"]) self.assertEqual(updated_profile.middle_name, self.profile_data["middle_name"]) self.assertEqual(updated_profile.last_name, self.profile_data["last_name"]) self.assertEqual(updated_profile.bio, self.profile_data["bio"]) def test_update_profile_not_found(self): """Test updating profile for non-existing user raises NotFoundError""" nonexistent_id = fake.pyint(min_value=900000, max_value=999999) with self.assertRaises(NotFoundError): ProfileService.update_profile(nonexistent_id, first_name=fake.first_name()) def test_get_full_profile_data_success(self): """Test getting full profile data""" profile_data = ProfileService.get_full_profile_data(self.user.id) self.assertIsNotNone(profile_data) self.assertEqual(profile_data["id"], self.user.id) self.assertEqual(profile_data["email"], self.user.email) self.assertEqual(profile_data["username"], self.user.username) self.assertEqual(profile_data["first_name"], self.profile.first_name) self.assertEqual(profile_data["middle_name"], self.profile.middle_name) self.assertEqual(profile_data["last_name"], self.profile.last_name) self.assertEqual(profile_data["full_name"], self.profile.full_name) self.assertEqual(profile_data["bio"], self.profile.bio) self.assertEqual(profile_data["is_verified"], self.user.is_verified) def test_get_full_profile_data_not_found(self): """Test getting full profile data for non-existing user raises NotFoundError""" nonexistent_id = fake.pyint(min_value=900000, max_value=999999) with self.assertRaises(NotFoundError): ProfileService.get_full_profile_data(nonexistent_id)