Skip to content

Commit 63985a2

Browse files
committed
feat: improved test coverage
1 parent 51d303c commit 63985a2

File tree

10 files changed

+109
-12
lines changed

10 files changed

+109
-12
lines changed

src/accounts/api/serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def validate(self, data):
9393

9494
if not account_confirmation.is_token_valid():
9595
raise serializers.ValidationError({"token": "Token is invalid or expired."})
96-
return {"token": data["token"]}
96+
return {"token": data["token"], "account_confirmation": account_confirmation}
9797

9898

9999
class EmailSerializer(serializers.Serializer):

src/accounts/api/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ def post(self, request):
324324
if not serializer.is_valid():
325325
return ErrorResponse(serializer.errors, status.HTTP_400_BAD_REQUEST)
326326

327-
account_confirmation = AccountConfirmation.objects.get(token=serializer.validated_data["token"])
327+
account_confirmation: AccountConfirmation = serializer.validated_data["account_confirmation"]
328328
account = account_confirmation.account
329329

330330
account.is_confirmed = True

src/central_command/settings.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,18 @@
165165
}
166166
}
167167

168+
169+
if "test" in sys.argv:
170+
DATABASES["default"] = {
171+
"ENGINE": "django.db.backends.sqlite3",
172+
"NAME": ":memory:",
173+
}
174+
175+
CACHES["default"] = {
176+
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
177+
"LOCATION": "tests",
178+
}
179+
168180
REST_FRAMEWORK = {
169181
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
170182
"DEFAULT_AUTHENTICATION_CLASSES": ["knox.auth.TokenAuthentication"],
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from django.core.cache import cache
2+
from django.urls import reverse
3+
from rest_framework import status
4+
from rest_framework.test import APITestCase
5+
6+
from accounts.models import Account, AccountConfirmation
7+
8+
9+
class ConfirmAccountTest(APITestCase):
10+
def setUp(self) -> None:
11+
cache.clear()
12+
self.account = Account.objects.create_user(
13+
username="confirmUser",
14+
15+
unique_identifier="confirmUser",
16+
)
17+
self.account.set_password("aValidPss963")
18+
self.account.is_confirmed = False
19+
self.account.save()
20+
21+
self.confirmation = AccountConfirmation.objects.create(account=self.account, token="confirm-token") # noqa: S106 - test-only credential
22+
self.url = reverse("account:confirm")
23+
24+
def test_confirm_account_with_valid_token(self) -> None:
25+
response = self.client.post(self.url, {"token": self.confirmation.token}, format="json")
26+
27+
self.assertEqual(response.status_code, status.HTTP_200_OK)
28+
29+
self.account.refresh_from_db()
30+
self.assertTrue(self.account.is_confirmed)
31+
self.assertFalse(AccountConfirmation.objects.filter(pk=self.confirmation.pk).exists())
32+
33+
def test_confirm_account_with_invalid_token(self) -> None:
34+
response = self.client.post(self.url, {"token": "invalid-token"}, format="json")
35+
36+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
37+
self.account.refresh_from_db()
38+
self.assertFalse(self.account.is_confirmed)

src/tests/accounts/endpoints/test_login_credentials.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from django.core.cache import cache
12
from django.urls import reverse
23
from rest_framework import status
34
from rest_framework.test import APITestCase
@@ -7,6 +8,7 @@
78

89
class LoginCredentialsTest(APITestCase):
910
def setUp(self):
11+
cache.clear()
1012
self.url = reverse("account:login-credentials")
1113
self.valid_account = Account.objects.create_user(
1214
username="validUser",

src/tests/accounts/endpoints/test_login_token.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from django.core.cache import cache
12
from django.urls import reverse
23
from rest_framework import status
34
from rest_framework.test import APITestCase
@@ -7,6 +8,7 @@
78

89
class LoginTokenTest(APITestCase):
910
def setUp(self):
11+
cache.clear()
1012
self.url = reverse("account:login-token")
1113
self.valid_account = Account.objects.create_user(
1214
username="validUser",

src/tests/accounts/endpoints/test_register.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from unittest.mock import patch
2+
3+
from django.core.cache import cache
14
from django.urls import reverse
25
from rest_framework import status
36
from rest_framework.test import APITestCase
@@ -7,6 +10,7 @@
710

811
class RegisterTest(APITestCase):
912
def setUp(self):
13+
cache.clear()
1014
self.url = reverse("account:register")
1115
self.valid_data = {
1216
"email": "[email protected]",
@@ -101,3 +105,15 @@ def test_confirmed_state_at_registering(self):
101105
self.assertEqual(response.status_code, status.HTTP_200_OK)
102106
created_account = Account.objects.get(email=self.valid_data["email"])
103107
self.assertFalse(created_account.is_confirmed)
108+
109+
def test_register_sends_confirmation_email(self):
110+
data = self.valid_data.copy()
111+
data["email"] = "[email protected]"
112+
data["unique_identifier"] = "newuser"
113+
data["username"] = "newuser"
114+
115+
with patch("accounts.models.Account.send_confirmation_mail") as mock_send:
116+
response = self.client.post(self.url, data, format="json")
117+
118+
self.assertEqual(response.status_code, status.HTTP_200_OK)
119+
mock_send.assert_called_once()

src/tests/accounts/endpoints/test_reset_password.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from unittest.mock import patch
2+
3+
from django.core.cache import cache
14
from django.urls import reverse
25
from rest_framework import status
36
from rest_framework.test import APITestCase
@@ -11,6 +14,7 @@ def get_reset_url(token):
1114

1215
class PasswordResetTest(APITestCase):
1316
def setUp(self):
17+
cache.clear()
1418
self.valid_account = Account.objects.create_user(
1519
username="validUser",
1620
@@ -37,6 +41,16 @@ def test_request_password_reset_with_valid_email(self):
3741
password_reset_request = PasswordResetRequestModel.objects.first()
3842
self.assertIsNotNone(password_reset_request)
3943

44+
def test_request_password_reset_sends_email(self):
45+
data = {"email": "[email protected]"}
46+
47+
with patch("accounts.api.views.send_email_with_template") as mock_send:
48+
response = self.client.post(self.url_request, data, format="json")
49+
50+
self.assertEqual(response.status_code, status.HTTP_200_OK)
51+
mock_send.assert_called_once()
52+
self.assertEqual(mock_send.call_args.kwargs["recipient"], data["email"])
53+
4054
def test_request_password_reset_with_invalid_email(self):
4155
data = {"email": "[email protected]"}
4256

src/tests/accounts/endpoints/test_server_verification_token.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from django.core.cache import cache
12
from django.urls import reverse
23
from rest_framework import status
34
from rest_framework.test import APITestCase
@@ -7,6 +8,7 @@
78

89
class ServerVerificationTokenTest(APITestCase):
910
def setUp(self):
11+
cache.clear()
1012
self.valid_account = Account.objects.create_user(
1113
username="validUser",
1214
@@ -57,6 +59,8 @@ def test_verify_with_invalid_token(self):
5759
def test_verify_with_invalid_identifier(self):
5860
self.client.credentials(HTTP_AUTHORIZATION=f"Token {self.token}")
5961
response = self.client.get(self.url_request, format="json")
62+
self.assertEqual(response.status_code, status.HTTP_200_OK)
63+
self.assertIn("verification_token", response.data)
6064

6165
data = {"verification_token": response.data["verification_token"], "unique_identifier": "invalidIdentifier"}
6266
response = self.client.post(self.url_verify, data, format="json")

src/tests/baby_serverlist/test_api.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from datetime import UTC, datetime
1+
from datetime import UTC, datetime, timedelta
2+
from uuid import uuid4
23

34
from django.core.cache import cache
4-
from django.test import override_settings
55
from django.urls import reverse
66
from rest_framework import status
77
from rest_framework.test import APITestCase
@@ -39,14 +39,6 @@ def _sample_status_payload(server_token: str) -> dict[str, object]:
3939
}
4040

4141

42-
@override_settings(
43-
CACHES={
44-
"default": {
45-
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
46-
"LOCATION": "baby-serverlist-tests",
47-
}
48-
}
49-
)
5042
class BabyServerAPITests(APITestCase):
5143
def setUp(self) -> None:
5244
self.user = Account.objects.create_user(
@@ -102,6 +94,17 @@ def test_regenerate_token_rejects_non_owner(self) -> None:
10294

10395
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
10496

97+
def test_regenerate_token_not_found_returns_404(self) -> None:
98+
self.client.force_authenticate(self.user)
99+
100+
response = self.client.post(
101+
reverse("baby_serverlist:regenerate-token"),
102+
{"server_id": str(uuid4())},
103+
format="json",
104+
)
105+
106+
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
107+
105108
def test_post_server_status_stores_payload_in_cache(self) -> None:
106109
baby_server = BabyServer.objects.create(owner=self.user, whitelisted=True)
107110
payload = _sample_status_payload(baby_server.serverlist_token)
@@ -151,6 +154,12 @@ def test_list_owned_baby_servers_live_flag(self) -> None:
151154
response = self.client.get(reverse("baby_serverlist:list-owned"))
152155
self.assertTrue(response.json()[0]["live"])
153156

157+
stale_time = datetime.now(tz=UTC) - timedelta(seconds=13)
158+
set_baby_server_heartbeat(str(baby_server.id), stale_time.isoformat())
159+
160+
response = self.client.get(reverse("baby_serverlist:list-owned"))
161+
self.assertFalse(response.json()[0]["live"])
162+
154163
def test_list_baby_servers_returns_whitelisted_status(self) -> None:
155164
baby_server = BabyServer.objects.create(owner=self.user, whitelisted=True)
156165
status_data = _sample_status_payload(baby_server.serverlist_token)

0 commit comments

Comments
 (0)