diff --git a/backend/videoflix/auth/tests.py b/backend/videoflix/auth/tests.py index 7ce503c..32f874e 100644 --- a/backend/videoflix/auth/tests.py +++ b/backend/videoflix/auth/tests.py @@ -1,3 +1,160 @@ -from django.test import TestCase +from django.urls import reverse +from rest_framework import status +from rest_framework.test import APITestCase +from rest_framework.authtoken.models import Token +from users.models import CustomUser -# Create your tests here. +class AuthTests(APITestCase): + """ + Prepares the test environment by creating an active user and an authentication token. + """ + def setUp(self): + self.user = CustomUser.objects.create_user( + username='testuser', email='testuser@example.com', password='testpass' + ) + self.user.is_active = True + self.user.save() + self.token = Token.objects.create(user=self.user) + + def test_login(self): + """ + Tests whether an active user can log in successfully. + """ + url = reverse('login') + data = {'email': 'testuser@example.com', 'password': 'testpass'} + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertIn('token', response.data) + + def test_login_inactive_user(self): + """ + Tests that an inactive user cannot log in. + """ + self.user.is_active = False + self.user.save() + url = reverse('login') + data = {'email': 'testuser@example.com', 'password': 'testpass'} + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + def test_register(self): + """ + Tests the registration of a new user and their inactivity after registration. + """ + url = reverse('register') + data = {'email': 'newuser@example.com', 'password': 'newpass', 'username': 'newuser'} + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertFalse(CustomUser.objects.get(email='newuser@example.com').is_active) + + def test_register_existing_user(self): + """ + Tests that registration with an existing e-mail fails. + """ + url = reverse('register') + data = {'email': 'testuser@example.com', 'password': 'newpass'} + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + def test_verify_email(self): + """ + Tests email verification for an inactive user. + """ + self.user.is_active = False + self.user.verify_email_token = 'validtoken' + self.user.save() + url = reverse('verify_email') + data = {'email': 'testuser@example.com', 'token': 'validtoken'} + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.user.refresh_from_db() + self.assertTrue(self.user.is_active) + + def test_verify_email_already_active(self): + """ + Tests that an already active user receives an error message during e-mail verification. + """ + email = 'testuser@example.com' + token = 'anytoken' + user = CustomUser.objects.create(email=email, verify_email_token=token, is_active=True) + url = reverse('verify_email') + data = {'email': email, 'token': token} + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_409_CONFLICT) + + def test_verify_email_invalid(self): + """ + Tests the e-mail verification with invalid data. + """ + url = reverse('verify_email') + data = {'email': 'invalid@example.com', 'token': 'invalidtoken'} + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + def test_forgot_password(self): + """ + Tests the forget password functionality and the generation of a new token. + """ + url = reverse('forgot_password') + data = {'email': 'testuser@example.com'} + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.user.refresh_from_db() + self.assertIsNotNone(self.user.verify_email_token) + + def test_forgot_password_invalid_email(self): + """ + Tests the forgot password functionality with an invalid e-mail address. + """ + url = reverse('forgot_password') + data = {'email': 'invalid@example.com'} + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + def test_change_password(self): + """ + Tests the password change with a valid token. + """ + self.user.verify_email_token = 'validtoken' + self.user.save() + url = reverse('change_password') + data = {'email': 'testuser@example.com', 'token': 'validtoken', 'new_password': 'newpass123'} + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.user.refresh_from_db() + self.assertTrue(self.user.check_password('newpass123')) + + def test_change_password_invalid_token(self): + """ + Tests the password change with an invalid token. + """ + url = reverse('change_password') + data = {'email': 'testuser@example.com', 'token': 'invalidtoken', 'new_password': 'newpass123'} + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + def test_auth_view_get_authenticated(self): + """ + Tests access to a protected view with authentication. + """ + self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token.key) + url = reverse('auth_view') + response = self.client.get(url) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_auth_view_get_unauthenticated(self): + """ + Tests access to a protected view without authentication. + """ + url = reverse('auth_view') + response = self.client.get(url) + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + + def test_auth_view_post_existing_user(self): + """ + Tests access to a protected view with an existing user. + """ + url = reverse('auth_view') + data = {'email': 'testuser@example.com'} + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) \ No newline at end of file diff --git a/backend/videoflix/auth/views.py b/backend/videoflix/auth/views.py index 5f05d72..e67556e 100644 --- a/backend/videoflix/auth/views.py +++ b/backend/videoflix/auth/views.py @@ -34,8 +34,8 @@ class LoginView(APIView): def _create_token_response(self, user): token, created = Token.objects.get_or_create(user=user) - return Response({token.key}, status=status.HTTP_200_OK) - + return Response({'token': token.key}, status=status.HTTP_200_OK) + class RegisterView(APIView): def post(self, request): email = request.data.get('email') @@ -89,6 +89,7 @@ class VerifyEmailView(APIView): return Response(status=status.HTTP_200_OK) else: return Response({"error": "Invalid email or token."}, status=status.HTTP_400_BAD_REQUEST) + class ForgotPasswordView(APIView): def post(self, request): diff --git a/backend/videoflix/videoflix/urls.py b/backend/videoflix/videoflix/urls.py index 25d9cfe..22a4e80 100644 --- a/backend/videoflix/videoflix/urls.py +++ b/backend/videoflix/videoflix/urls.py @@ -45,10 +45,10 @@ urlpatterns = [ path('users//', user_views.user_detail, name='user_detail'), # Authentication URLs - path('auth/', AuthView.as_view()), - path('auth/login/', LoginView.as_view()), - path('auth/register/', RegisterView.as_view()), - path('auth/verify-email/', VerifyEmailView.as_view()), - path('auth/forgot-password/', ForgotPasswordView.as_view()), - path('auth/change-password/', ChangePasswordView.as_view()), + path('auth/', AuthView.as_view(), name='auth_view'), + path('auth/login/', LoginView.as_view(), name='login'), + path('auth/register/', RegisterView.as_view(), name='register'), + path('auth/verify-email/', VerifyEmailView.as_view(), name='verify_email'), + path('auth/forgot-password/', ForgotPasswordView.as_view(), name='forgot_password'), + path('auth/change-password/', ChangePasswordView.as_view(), name='change_password'), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + debug_toolbar_urls() + staticfiles_urlpatterns() \ No newline at end of file