Files
mostovik-backend/tests/apps/user/test_services.py

337 lines
14 KiB
Python

"""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_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)[:2])
self.assertEqual(ids, [second.id, 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)