From b8d9f5cf87286267e13e06f7e1bd5016472b2bc7 Mon Sep 17 00:00:00 2001 From: i701 Date: Fri, 11 Apr 2025 17:06:28 +0500 Subject: [PATCH] Refactor VerifyPaymentView to include checks for payment status and user authorization. Update logging level in settings.py to suppress certain logs during testing. Add comprehensive tests for device management in DeviceAPITestCase. --- .vscode/settings.json | 3 +- apibase/settings.py | 2 +- billing/views.py | 9 ++++- devices/tests.py | 80 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 89 insertions(+), 5 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 5fd0503..f961bde 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,5 +8,6 @@ "*test.py" ], "python.testing.pytestEnabled": false, - "python.testing.unittestEnabled": true + "python.testing.unittestEnabled": true, + "postman.settings.dotenv-detection-notification-visibility": false } \ No newline at end of file diff --git a/apibase/settings.py b/apibase/settings.py index 9413ca7..bc525e0 100644 --- a/apibase/settings.py +++ b/apibase/settings.py @@ -330,7 +330,7 @@ logging.config.dictConfig( "propagate": False, }, "django.request": { - "level": "WARNING", + "level": "ERROR", # Suppress 400/403/404 logs for test cases "handlers": ["request"], "propagate": False, }, diff --git a/billing/views.py b/billing/views.py index b2c4e95..776b0f9 100644 --- a/billing/views.py +++ b/billing/views.py @@ -108,6 +108,13 @@ class VerifyPaymentView(StaffEditorPermissionMixin, generics.UpdateAPIView): payment = self.get_object() data = request.data user = request.user + print("logged in user", user) + print("Payment user", payment.user) + if payment.paid: + return Response( + {"message": "Payment has already been verified."}, + status=status.HTTP_400_BAD_REQUEST, + ) if payment.user != user and not user.is_superuser: return Response( {"message": "You are not authorized to verify this payment."}, @@ -156,7 +163,7 @@ class VerifyPaymentView(StaffEditorPermissionMixin, generics.UpdateAPIView): ) else: return Response( - {"message": "Payment verification FAILED using [{method}]."} + {"message": f"Payment verification FAILED using [{method}]."} ) def process_wallet_payment(self, user, payment): diff --git a/devices/tests.py b/devices/tests.py index 7ce503c..efc28f6 100644 --- a/devices/tests.py +++ b/devices/tests.py @@ -1,3 +1,79 @@ -from django.test import TestCase +from rest_framework.test import APITestCase +from rest_framework import status +from django.contrib.auth import get_user_model +from .models import Device +from django.contrib.auth.models import Permission -# Create your tests here. +User = get_user_model() + + +class DeviceAPITestCase(APITestCase): + def setUp(self): + self.user = User.objects.create_user(username="testuser", password="password") + self.user.user_permissions.add( + Permission.objects.get(codename="add_device"), + Permission.objects.get(codename="delete_device"), + Permission.objects.get(codename="view_device"), + Permission.objects.get(codename="change_device"), + ) + self.superuser = User.objects.create_superuser( + username="admin", password="password", email="admin@example.com" + ) + self.device = Device.objects.create( + name="Test Device", mac="00:1A:2B:3C:4D:5E", user=self.user + ) + self.client.login( + username="testuser", password="password", email="admin@example.com" + ) + self.token = self.client.post( + "/api/auth/login/", + {"username": "admin@example.com", "password": "password"}, + ).data["token"] + + def test_list_devices(self): + self.client.credentials(HTTP_AUTHORIZATION=f"Token {self.token}") + response = self.client.get("/api/devices/") + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_create_device(self): + self.client.credentials(HTTP_AUTHORIZATION=f"Token {self.token}") + data = {"name": "New Device", "mac": "11:22:33:44:55:66"} + response = self.client.post("/api/devices/", data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + def test_create_device_invalid_mac(self): + self.client.credentials(HTTP_AUTHORIZATION=f"Token {self.token}") + data = {"name": "Invalid Device", "mac": "invalid-mac"} + response = self.client.post("/api/devices/", data) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertIn("Invalid mac address.", response.data["message"]) + + def test_update_device(self): + self.client.credentials(HTTP_AUTHORIZATION=f"Token {self.token}") + data = {"name": "Updated Device"} + response = self.client.patch(f"/api/devices/{self.device.pk}/update/", data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.device.refresh_from_db() + self.assertEqual(self.device.name, "Updated Device") + + def test_block_device(self): + self.client.credentials(HTTP_AUTHORIZATION=f"Token {self.token}") + data = { + "blocked": True, # also use Python boolean here, not a string + "reason_for_blocking": "hello", + "blocked_by": "ADMIN", + } + response = self.client.put( + f"/api/devices/{self.device.pk}/block/", + data, + format="json", # ✅ this is crucial! + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.device.refresh_from_db() + self.assertTrue(self.device.blocked) + + def test_delete_device(self): + self.client.credentials(HTTP_AUTHORIZATION=f"Token {self.token}") + response = self.client.delete(f"/api/devices/{self.device.pk}/delete/") + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertFalse(Device.objects.filter(pk=self.device.pk).exists())