From 92838f1dde56be2309808d6698a70681c9df05d7 Mon Sep 17 00:00:00 2001 From: behruz-dev Date: Tue, 15 Jul 2025 12:41:44 +0500 Subject: [PATCH] write auth tests with pytest --- core/apps/accounts/__init__.py | 1 + core/apps/accounts/tests/test_auth.py | 237 ++++++++++++++++++++++++++ core/apps/accounts/urls.py | 2 +- core/apps/accounts/views/auth.py | 1 + pytest.ini | 3 + requirements.txt | 4 +- 6 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 core/apps/accounts/tests/test_auth.py create mode 100644 pytest.ini diff --git a/core/apps/accounts/__init__.py b/core/apps/accounts/__init__.py index e69de29..b8f079e 100644 --- a/core/apps/accounts/__init__.py +++ b/core/apps/accounts/__init__.py @@ -0,0 +1 @@ +from .tests import * \ No newline at end of file diff --git a/core/apps/accounts/tests/test_auth.py b/core/apps/accounts/tests/test_auth.py new file mode 100644 index 0000000..777fc11 --- /dev/null +++ b/core/apps/accounts/tests/test_auth.py @@ -0,0 +1,237 @@ +import pytest +from datetime import timedelta + +from django.contrib.auth import get_user_model +from django.contrib.auth.hashers import make_password +from django.urls import reverse +from django.utils import timezone + +from rest_framework.test import APIClient + +from core.apps.accounts.models.verification_code import VerificationCode + + +@pytest.mark.django_db +class TestLoginAPI: + @pytest.fixture(autouse=True) + def setup(self): + self.client = APIClient() + self.password = '20090912' + self.phone = '+998947099971' + self.user = get_user_model().objects.create_user( + phone=self.phone, password=self.password + ) + self.new_user_phone = '+998947099972' + self.new_user = get_user_model().objects.create_user( + phone=self.new_user_phone, password=self.password, is_active=False + ) + # self.code = VerificationCode.objects.create(user=self.new_user, code=1111) + + def test_login_success(self): + url = reverse('login') + response = self.client.post(url, { + "phone": self.phone, + "password": self.password + }) + + assert response.status_code == 200 + assert 'access_token' in response.data + assert 'refresh_token' in response.data + assert 'role' in response.data + + def test_login_user_not_found(self): + url = reverse('login') + response = self.client.post(url, { + 'phone': self.phone, + 'password': 'somepass' + }) + assert response.status_code == 400 + assert 'detail' in response.data + + def test_register_user(self): + url = reverse('register') + response = self.client.post(url, { + 'phone': '+998947099973', + 'password': self.password + }) + + assert response.status_code == 201 + assert 'phone' in response.data + + def test_register_user_exists(self): + url = reverse('register') + response = self.client.post(url, { + 'phone': '+998947099971', + 'password': self.password + }) + + assert response.status_code == 400 + assert 'detail' in response.data + + def test_confirm_user(self): + time = timezone.now() + timedelta(minutes=2) + code = VerificationCode.objects.create(user=self.new_user, code=1111, expiration_time=time) + url = reverse('confirm-user') + response = self.client.post(url, { + 'phone': self.new_user_phone, + 'code': code.code + }) + + assert response.status_code == 202 + assert 'success' in response.data + assert 'message' in response.data + + def test_confirm_user_not_found(self): + time = timezone.now() + timedelta(minutes=2) + code = VerificationCode.objects.create(user=self.new_user, code=1111, expiration_time=time) + url = reverse('confirm-user') + response = self.client.post(url, { + 'phone': '+998999999999', + 'code': code.code + }) + + assert response.status_code == 400 + assert 'message' in response.data + assert 'detail' in response.data['message'] + assert 'success' in response.data + + def test_confirm_user_is_active(self): + time = timezone.now() + timedelta(minutes=2) + code = VerificationCode.objects.create(user=self.user, code=1111, expiration_time=time) + url = reverse('confirm-user') + response = self.client.post(url, { + 'phone': self.user, + 'code': code.code + }) + + assert response.status_code == 400 + assert 'message' in response.data + assert 'detail' in response.data['message'] + assert 'success' in response.data + + def test_confirm_user_code_is_expired(self): + time = timezone.now() + code = VerificationCode.objects.create(user=self.new_user, code=1111, expiration_time=time) + url = reverse('confirm-user') + response = self.client.post(url, { + 'phone': self.new_user, + 'code': code.code + }) + + assert response.status_code == 400 + assert 'message' in response.data + assert response.data['message'] == 'code is expired' + assert 'success' in response.data + + def test_confirm_user_code_is_verify(self): + time = timezone.now() + timedelta(minutes=2) + code = VerificationCode.objects.create(user=self.new_user, code=1111, expiration_time=time, is_verify=True) + url = reverse('confirm-user') + response = self.client.post(url, { + 'phone': self.new_user, + 'code': code.code + }) + + assert response.status_code == 400 + assert 'message' in response.data + assert response.data['message'] == 'code is verified' + assert 'success' in response.data + + def test_confirm_user_wrong_code(self): + time = timezone.now() + timedelta(minutes=2) + code = VerificationCode.objects.create(user=self.user, code=1111, expiration_time=time, is_verify=True) + url = reverse('confirm-user') + response = self.client.post(url, { + 'phone': self.new_user, + 'code': code.code + }) + + assert response.status_code == 400 + assert 'message' in response.data + assert response.data['message'] == 'code is wrong' + assert 'success' in response.data + + def test_confirm_user_serializer_error(self): + time = timezone.now() + timedelta(minutes=2) + code = VerificationCode.objects.create(user=self.user, code=1111, expiration_time=time, is_verify=True) + url = reverse('confirm-user') + response = self.client.post(url, { + 'code': code.code + }) + print(response.data) + assert response.status_code == 400 + assert 'message' in response.data + assert response.data['message']['phone'][0] == "Ushbu maydon to'ldirilishi shart." + assert 'success' in response.data + + def test_choice_user_role_success(self): + url = reverse('choise-user-role') + response = self.client.post(url, { + 'phone': self.new_user_phone, + 'role': 'LP', + }) + assert response.status_code == 200 + assert response.data['success'] == True + assert response.data['message'] == 'role is selected' + + def test_choice_user_role_user_404(self): + url = reverse('choise-user-role') + response = self.client.post(url, { + 'phone': self.user, + 'role': 'LP', + }) + assert response.status_code == 400 + assert response.data['success'] == False + assert response.data['message']['detail'][0] == 'user not found' + + def test_choice_user_role_wrong_choice(self): + url = reverse('choise-user-role') + response = self.client.post(url, { + 'phone': self.new_user, + 'role': 'LL', + }) + assert response.status_code == 400 + assert response.data['success'] == False + assert response.data['message']['role'][0] == '"LL" is not a valid choice.' + + def test_complite_user_profile_success(self): + url = reverse('complite-user-profile', kwargs={"phone": self.user.phone}) + response = self.client.put(url, data={ + 'first_name': 'behruz', + 'last_name': 'xoliqberdiyev', + 'email': 'xoliqberdiyev@gmail.com' + }) + + assert response.status_code == 200 + assert 'access_token' in response.data + assert 'refresh_token' in response.data + + def test_complite_user_profile_user_404(self): + url = reverse('complite-user-profile', kwargs={"phone": self.new_user.phone}) + response = self.client.put(url, data={ + 'first_name': 'behruz', + 'last_name': 'xoliqberdiyev', + 'email': 'xoliqberdiyev@gmail.com' + }) + + assert response.status_code == 404 + assert 'access_token' not in response.data + assert 'refresh_token' not in response.data + + def test_complite_user_profile_user_404(self): + url = reverse('complite-user-profile', kwargs={"phone": self.user.phone}) + response1 = self.client.put(url, data={ + 'first_name': 'behruz', + 'last_name': 'xoliqberdiyev', + 'email': 'xoliqberdiyev@gmail.com' + }) + + response2 = self.client.put(url, data={ + 'first_name': 'behruz', + 'last_name': 'xoliqberdiyev', + 'email': 'xoliqberdiyev@gmail.com' + }) + + assert response1.status_code == 200 + assert response2.status_code == 400 + assert response2.data['message']['detail'][0] == 'User with this email already exists' \ No newline at end of file diff --git a/core/apps/accounts/urls.py b/core/apps/accounts/urls.py index 424f950..ca93b7d 100644 --- a/core/apps/accounts/urls.py +++ b/core/apps/accounts/urls.py @@ -6,7 +6,7 @@ urlpatterns = [ path('auth/', include( [ path('login/', LoginApiView.as_view(), name='login'), - path('register/', RegisterApiView.as_view(), name='login'), + path('register/', RegisterApiView.as_view(), name='register'), path('confirm_user/', ConfirUserApiView.as_view(), name='confirm-user'), path('choise_user_role/', ChoiceUserRoleApiView.as_view(), name='choise-user-role'), path('complite_user_profile//', CompliteUserProfileApiView.as_view(), name='complite-user-profile'), diff --git a/core/apps/accounts/views/auth.py b/core/apps/accounts/views/auth.py index fc9bf38..bad36dd 100644 --- a/core/apps/accounts/views/auth.py +++ b/core/apps/accounts/views/auth.py @@ -25,6 +25,7 @@ class LoginApiView(generics.GenericAPIView): user = serializer.validated_data.get('user') tokens = RefreshToken.for_user(user) return Response({'access_token': str(tokens.access_token), 'refresh_token': str(tokens), 'role': user.role}, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_404_NOT_FOUND) @extend_schema(tags=['auth']) diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..ec3a0a8 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +DJANGO_SETTINGS_MODULE = config.settings.base +python_files = test_*.py \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 79bf393..771da6a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,6 @@ djangorestframework requests celery==5.5.3 redis==6.2.0 -django-redis==6.0.0 \ No newline at end of file +django-redis==6.0.0 +pytest +pytest-django \ No newline at end of file