From 61ab72be1d88b9a09485fdc9534f0771da45903e Mon Sep 17 00:00:00 2001 From: imbeer Date: Wed, 28 May 2025 14:10:54 +0300 Subject: [PATCH 1/2] #73: add subscription tests --- backend/taskbench/tests/test_subscription.py | 168 +++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 backend/taskbench/tests/test_subscription.py diff --git a/backend/taskbench/tests/test_subscription.py b/backend/taskbench/tests/test_subscription.py new file mode 100644 index 00000000..71b3fddc --- /dev/null +++ b/backend/taskbench/tests/test_subscription.py @@ -0,0 +1,168 @@ +from django.test import TestCase, Client +from django.urls import reverse +from rest_framework import status +from rest_framework.test import APIClient + +from taskbench.models.models import User, Subscription + + +class SubscriptionAPITests(TestCase): + def setUp(self): + self.client = APIClient() + + self.user1 = User.objects.create( + email='test_for_sub@example.com' + ) + self.user1.set_password('testpass123') + self.user1.save() + + self.user2 = User.objects.create( + email='test_for_sub2@example.com' + ) + self.user2.set_password('testpass123') + self.user2.save() + + self.user3 = User.objects.create( + email='test_for_sub3@example.com' + ) + self.user3.set_password('testpass123') + self.user3.save() + + self.user4 = User.objects.create( + email='test_for_sub4@example.com' + ) + self.user4.set_password('testpass123') + self.user4.save() + + self.subscription2 = Subscription.objects.create( + user=self.user2, + ) + self.subscription2.activate(0) + + self.subscription3 = Subscription.objects.create( + user=self.user3, + ) + self.subscription3.activate(1) + + self.subscription4 = Subscription.objects.create( + user=self.user4, + ) + self.subscription4.activate(2) + self.subscription4.deactivate() + + def test_unsubscribed(self): + url = reverse('login') + response = self.client.post( + url, + data={ + "email": "test_for_sub@example.com", + "password": "testpass123" + }, + format='json') + access = str(response.json().get('access')) + + url = reverse('subscription_status') + response = self.client.get( + url, + HTTP_AUTHORIZATION=f'Bearer {access}', + format='json' + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + is_subscribed = bool(response.json().get('is_subscribed')) + self.assertFalse(is_subscribed) + + def test_subscribed(self): + url = reverse('login') + response = self.client.post( + url, + data={ + "email": "test_for_sub2@example.com", + "password": "testpass123" + }, + format='json') + access = str(response.json().get('access')) + + url = reverse('subscription_status') + response = self.client.get( + url, + HTTP_AUTHORIZATION=f'Bearer {access}', + format='json') + + self.assertEqual(response.status_code, status.HTTP_200_OK) + subscription_id = int(response.json().get('subscription_id')) + is_subscribed = bool(response.json().get('is_subscribed')) + self.assertTrue(is_subscribed) + self.assertEqual(subscription_id, self.subscription2.subscription_id) + + def test_deactivate(self): + url = reverse('login') + response = self.client.post( + url, + data={ + "email": "test_for_sub3@example.com", + "password": "testpass123" + }, + format='json') + access = str(response.json().get('access')) + + url = reverse('subscription_status') + response = self.client.get( + url, + HTTP_AUTHORIZATION=f'Bearer {access}', + format='json') + is_active = bool(response.json().get('is_active')) + self.assertTrue(is_active) + + url = reverse('manage_subscription') + response = self.client.delete( + url, + HTTP_AUTHORIZATION=f'Bearer {access}', + format='json') + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + + url = reverse('subscription_status') + response = self.client.get( + url, + HTTP_AUTHORIZATION=f'Bearer {access}', + format='json') + is_active = bool(response.json().get('is_active')) + is_subscribed = bool(response.json().get('is_subscribed')) + self.assertFalse(is_active) + self.assertTrue(is_subscribed) + + def test_activate(self): + url = reverse('login') + response = self.client.post( + url, + data={ + "email": "test_for_sub4@example.com", + "password": "testpass123" + }, + format='json') + access = str(response.json().get('access')) + + url = reverse('subscription_status') + response = self.client.get( + url, + HTTP_AUTHORIZATION=f'Bearer {access}', + format='json') + is_active = bool(response.json().get('is_active')) + self.assertFalse(is_active) + + url = reverse('manage_subscription') + response = self.client.post( + url, + HTTP_AUTHORIZATION=f'Bearer {access}', + format='json') + subscription_id = int(response.json().get('subscription_id')) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(subscription_id, self.subscription4.subscription_id) + + url = reverse('subscription_status') + response = self.client.get( + url, + HTTP_AUTHORIZATION=f'Bearer {access}', + format='json') + is_active = bool(response.json().get('is_active')) + self.assertTrue(is_active) From 21d478c3cfeeb779b7daedff4ebbb0276e951632 Mon Sep 17 00:00:00 2001 From: imbeer Date: Wed, 28 May 2025 14:12:54 +0300 Subject: [PATCH 2/2] #73: clean up previous fake subscription API --- backend/backend/urls.py | 6 +- backend/subscription/views.py | 2 +- backend/taskbench/tests/test_user_api.py | 52 +++++++-------- backend/taskbench/views/user_views.py | 82 +++--------------------- 4 files changed, 38 insertions(+), 104 deletions(-) diff --git a/backend/backend/urls.py b/backend/backend/urls.py index 3c64f7d0..99f2ac88 100644 --- a/backend/backend/urls.py +++ b/backend/backend/urls.py @@ -16,9 +16,7 @@ LoginView, DeleteUserView, TokenRefreshView, - ChangePasswordView, - # SubscriptionStatusView, - # CreateSubscriptionView + ChangePasswordView ) urlpatterns = [ @@ -36,7 +34,5 @@ path('token/refresh/', TokenRefreshView.as_view(), name="token_refresh"), path('statistics/', StatisticsView.as_view(), name='statistics'), path('ai/suggestions/', SuggestionView.as_view(), name="ai_suggestions"), - # path('user/subscription/status/', SubscriptionStatusView.as_view()), - # path('user/subscription/', CreateSubscriptionView.as_view()), ] diff --git a/backend/subscription/views.py b/backend/subscription/views.py index da960c70..2aefc861 100644 --- a/backend/subscription/views.py +++ b/backend/subscription/views.py @@ -28,7 +28,7 @@ def delete(self, request, *args, **kwargs): try: token = get_token(request) cancel_subscription(token) - return Response(status=200) + return Response(status=204) except NotFound as e: return Response({'error': e.message}, status=400) except AuthenticationError as e: diff --git a/backend/taskbench/tests/test_user_api.py b/backend/taskbench/tests/test_user_api.py index e5a23f2e..10aab296 100644 --- a/backend/taskbench/tests/test_user_api.py +++ b/backend/taskbench/tests/test_user_api.py @@ -20,46 +20,48 @@ def setUp(self): def test_login_and_password_change(self): url = reverse('login') - response = self.client.post(url, - data={ - "email": "example@mail.com", - "password": "test_password" - }, format='json') + response = self.client.post( + url, + data={ + "email": "example@mail.com", + "password": "test_password" + }, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.json().get('access')) self.assertIsNotNone(response.json().get('refresh')) access = str(response.json().get('access')) url = reverse('change_password') - response = self.client.patch(url, - data={ - "old_password": "test_password", - "new_password": "new_password" - }, - HTTP_AUTHORIZATION=f'Bearer {access}', - format='json') + response = self.client.patch( + url, + data={ + "old_password": "test_password", + "new_password": "new_password" + }, + HTTP_AUTHORIZATION=f'Bearer {access}', + format='json') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) url = reverse('login') - response = self.client.post(url, - data={ - "email": "example@mail.com", - "password": "new_password" - }, - format='json') + response = self.client.post( + url, + data={ + "email": "example@mail.com", + "password": "new_password" + }, + format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIsNotNone(response.json().get('access')) self.assertIsNotNone(response.json().get('refresh')) - - def test_register_refresh_and_delete(self): url = reverse('register') - response = self.client.post(url, - data={ - "email": 'new_email@mail.com', - "password": "test_password" - }, format='json') + response = self.client.post( + url, + data={ + "email": 'new_email@mail.com', + "password": "test_password" + }, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertIsNotNone(response.json().get('access')) self.assertIsNotNone(response.json().get('refresh')) diff --git a/backend/taskbench/views/user_views.py b/backend/taskbench/views/user_views.py index e0ac5ba4..a7262d2e 100644 --- a/backend/taskbench/views/user_views.py +++ b/backend/taskbench/views/user_views.py @@ -1,15 +1,11 @@ import json -import uuid -from datetime import timedelta from django.http import JsonResponse -from django.utils import timezone from pydantic import ValidationError from rest_framework.response import Response from rest_framework.views import APIView -from ..models.models import Subscription -from ..serializers.user_serializers import JwtSerializer, user_response +from ..serializers.user_serializers import user_response from ..services.user_service import get_token, register_user, login_user, token_refresh, delete_user, change_password, \ AuthenticationError @@ -17,8 +13,8 @@ class RegisterView(APIView): def post(self, request, *args, **kwargs): - data = json.loads(request.body) try: + data = json.loads(request.body) return user_response(*register_user(data), status=201) except Exception as e: return JsonResponse({'error': str(e)}, status=400) @@ -27,10 +23,11 @@ def post(self, request, *args, **kwargs): class LoginView(APIView): def post(self, request, *args, **kwargs): - data = json.loads(request.body) try: + data = json.loads(request.body) return user_response(*login_user(data), status=200) except Exception as e: + print(str(e)) return JsonResponse({'error': str(e)}, status=400) @@ -48,8 +45,8 @@ def delete(self, request, *args, **kwargs): class ChangePasswordView(APIView): def patch(self, request, *args, **kwargs): - data = json.loads(request.body) try: + data = json.loads(request.body) change_password(token=get_token(request), data=data) return Response(status=204) except AuthenticationError as e: @@ -61,72 +58,11 @@ def patch(self, request, *args, **kwargs): class TokenRefreshView(APIView): def post(self, request, *args, **kwargs): - data = json.loads(request.body) - token = {'token': str(data['refresh'])} - if data['refresh'] is None: - return Response('No token provided.', status=400) try: + data = json.loads(request.body) + token = {'token': str(data['refresh'])} + if data['refresh'] is None: + return Response('No token provided.', status=400) return user_response(*token_refresh(token), status=200) except Exception as e: return JsonResponse({'error': str(e)}, status=400) - - -# class SubscriptionStatusView(APIView): -# def get(self, request): -# token = get_token(request) -# serializer = JwtSerializer(data=token) -# if not serializer.is_valid(): -# return JsonResponse({'error': 'Invalid token'}, status=401) -# user = serializer.validated_data['user'] -# -# # Проверяем активную подписку -# now = timezone.now() -# active_subscription = user.subscriptions.filter( -# is_active=True, -# start_date__lte=now, -# end_date__gte=now -# ).first() -# -# if active_subscription: -# return JsonResponse({ -# 'has_subscription': True, -# 'start_date': active_subscription.start_date, -# 'end_date': active_subscription.end_date, -# 'transaction_id': active_subscription.transaction_id -# }) -# else: -# return JsonResponse({ -# 'has_subscription': False -# }) -# -# -# class CreateSubscriptionView(APIView): -# def post(self, request): -# # Проверка JWT токена -# token = get_token(request) -# serializer = JwtSerializer(data=token) -# if not serializer.is_valid(): -# return JsonResponse({'error': 'Invalid token'}, status=401) -# user = serializer.validated_data['user'] -# -# now = timezone.now() -# end_date = now + timedelta(days=30) -# -# if user.subscriptions.filter(is_active=True, end_date__gte=now).exists(): -# return JsonResponse({'error': 'User already has active subscription'}, status=400) -# -# subscription = Subscription.objects.create( -# user=user, -# start_date=now, -# end_date=end_date, -# is_active=True, -# transaction_id=str(uuid.uuid4()) -# ) -# -# return JsonResponse({ -# 'status': 'success', -# 'subscription_id': subscription.subscription_id, -# 'start_date': subscription.start_date, -# 'end_date': subscription.end_date, -# 'transaction_id': subscription.transaction_id -# }, status=201)