From 4d89ddd2577cbf88cf1d6fdda0dc0923a05a8ac4 Mon Sep 17 00:00:00 2001 From: "Rudy (zarya)" Date: Tue, 13 May 2025 20:45:28 +0200 Subject: [PATCH 1/9] Token ruffing, added tests --- src/tokens/__init__.py | 1 + src/tokens/admin.py | 20 ++++++--- src/tokens/apps.py | 2 + src/tokens/models.py | 39 +++++++++++++----- src/tokens/templatetags/__init__.py | 1 + src/tokens/templatetags/token_tags.py | 12 +++++- src/tokens/tests/__init__.py | 1 + src/tokens/tests/test_views.py | 59 +++++++++++++++++++++++++++ src/tokens/urls.py | 1 + src/tokens/views.py | 23 ++++++++--- 10 files changed, 136 insertions(+), 23 deletions(-) create mode 100644 src/tokens/tests/__init__.py create mode 100644 src/tokens/tests/test_views.py diff --git a/src/tokens/__init__.py b/src/tokens/__init__.py index e69de29bb..901660801 100644 --- a/src/tokens/__init__.py +++ b/src/tokens/__init__.py @@ -0,0 +1 @@ +"""Init for application token.""" diff --git a/src/tokens/admin.py b/src/tokens/admin.py index d7c02c961..0445a9e73 100644 --- a/src/tokens/admin.py +++ b/src/tokens/admin.py @@ -1,5 +1,11 @@ +"""All Django admin views for application token.""" from __future__ import annotations +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from typing import ClassVar + from django.contrib import admin from .models import Token @@ -8,13 +14,15 @@ @admin.register(Token) class TokenAdmin(admin.ModelAdmin): - list_filter = ["camp", "category", "active"] - list_display = ["token", "description", "camp", "category", "active", "valid_when"] - search_fields = ["token", "description", "category"] + """Django admin for tokens.""" + list_filter: ClassVar[list[str]] = ["camp", "category", "active"] + list_display: ClassVar[list[str]] = ["token", "description", "camp", "category", "active", "valid_when"] + search_fields: ClassVar[list[str]] = ["token", "description", "category"] @admin.register(TokenFind) class TokenFindAdmin(admin.ModelAdmin): - list_filter = ["token__camp", "user"] - list_display = ["token", "user", "created"] - search_fields = ["user", "token"] + """Django admin for token finds.""" + list_filter: ClassVar[list[str]] = ["token__camp", "user"] + list_display: ClassVar[list[str]] = ["token", "user", "created"] + search_fields: ClassVar[list[str]] = ["user", "token"] diff --git a/src/tokens/apps.py b/src/tokens/apps.py index e36c9d430..3901ad513 100644 --- a/src/tokens/apps.py +++ b/src/tokens/apps.py @@ -1,7 +1,9 @@ +"""All apps for token application.""" from __future__ import annotations from django.apps import AppConfig class TokensConfig(AppConfig): + """TokensConfig.""" name = "tokens" diff --git a/src/tokens/models.py b/src/tokens/models.py index 8c2081c00..21bb3c35d 100644 --- a/src/tokens/models.py +++ b/src/tokens/models.py @@ -1,5 +1,8 @@ +"""All models for the token application.""" from __future__ import annotations +from typing import TYPE_CHECKING + from django.contrib.postgres.fields import DateTimeRangeField from django.db import models from django.urls import reverse @@ -8,8 +11,13 @@ from utils.models import CampRelatedModel +if TYPE_CHECKING: + from typing import ClassVar + + from camps.models import Camp class Token(ExportModelOperationsMixin("token"), CampRelatedModel): + """Secret Token model.""" camp = models.ForeignKey("camps.Camp", on_delete=models.PROTECT) token = models.CharField(max_length=32, help_text="The secret token") @@ -22,7 +30,9 @@ class Token(ExportModelOperationsMixin("token"), CampRelatedModel): active = models.BooleanField( default=False, - help_text="An active token is listed and can be found by players, an inactive token is unlisted and returns an error saying 'valid but inactive token found' to players who find it.", + help_text="An active token is listed and can be found by players, " + "an inactive token is unlisted and returns an error saying 'valid " + "but inactive token found' to players who find it.", ) valid_when = DateTimeRangeField( @@ -35,12 +45,15 @@ class Token(ExportModelOperationsMixin("token"), CampRelatedModel): camp_filter = "camp" def __str__(self) -> str: + """String formatter.""" return f"{self.description} ({self.camp})" class Meta: - ordering = ["camp"] + """Meta.""" + ordering: ClassVar[list[str]] = ["camp"] - def get_absolute_url(self): + def get_absolute_url(self) -> str: + """Get absolute url.""" return reverse( "backoffice:token_detail", kwargs={"camp_slug": self.camp.slug, "pk": self.pk}, @@ -48,20 +61,24 @@ def get_absolute_url(self): @property def valid_now(self) -> bool: + """Returns if the token is valid 'now'.""" + valid = False if not self.valid_when: # no time limit - return True - if self.valid_when.lower and self.valid_when.lower > timezone.now(): + valid = True + elif self.valid_when.lower and self.valid_when.lower > timezone.now(): # not valid yet - return False - if self.valid_when.upper and self.valid_when.upper < timezone.now(): + valid = False + elif self.valid_when.upper and self.valid_when.upper < timezone.now(): # not valid anymore - return False - return True + valid = False + return valid class TokenFind(ExportModelOperationsMixin("token_find"), CampRelatedModel): + """Model with all found Secret Tokens.""" class Meta: + """Meta.""" unique_together = ("user", "token") token = models.ForeignKey("tokens.Token", on_delete=models.PROTECT) @@ -75,8 +92,10 @@ class Meta: camp_filter = "token__camp" def __str__(self) -> str: + """String formatter.""" return f"{self.token} found by {self.user}" @property - def camp(self): + def camp(self) -> Camp: + """Property camp linked to this token find via Token.""" return self.token.camp diff --git a/src/tokens/templatetags/__init__.py b/src/tokens/templatetags/__init__.py index e69de29bb..ad524c89a 100644 --- a/src/tokens/templatetags/__init__.py +++ b/src/tokens/templatetags/__init__.py @@ -0,0 +1 @@ +"""Template tags for the Token application.""" diff --git a/src/tokens/templatetags/token_tags.py b/src/tokens/templatetags/token_tags.py index df6deb10e..1db4b8407 100644 --- a/src/tokens/templatetags/token_tags.py +++ b/src/tokens/templatetags/token_tags.py @@ -1,16 +1,24 @@ +"""Token template tags for the Token application.""" from __future__ import annotations +from typing import TYPE_CHECKING + from django import template from tokens.models import TokenFind +if TYPE_CHECKING: + from django.contrib.auth.models import User + register = template.Library() @register.filter -def found_by_user(token, user): +def found_by_user(token: str, user: User) -> bool: + """Template tag to show if the token is found.""" try: tokenfind = TokenFind.objects.get(token=token, user=user) - return tokenfind.created except TokenFind.DoesNotExist: return False + else: + return tokenfind.created diff --git a/src/tokens/tests/__init__.py b/src/tokens/tests/__init__.py new file mode 100644 index 000000000..a9aaa4aca --- /dev/null +++ b/src/tokens/tests/__init__.py @@ -0,0 +1 @@ +"""Init for tests of application tokens.""" diff --git a/src/tokens/tests/test_views.py b/src/tokens/tests/test_views.py new file mode 100644 index 000000000..085313444 --- /dev/null +++ b/src/tokens/tests/test_views.py @@ -0,0 +1,59 @@ +"""Tests for token views.""" + +from __future__ import annotations + +from bs4 import BeautifulSoup +from django.urls import reverse + +from tokens.models import Token +from utils.tests import BornhackTestBase + + +class TestTokenViews(BornhackTestBase): + """Test Phonebook view.""" + + token: Token + + @classmethod + def setUpTestData(cls) -> None: + """Add test data.""" + # first add users and other basics + super().setUpTestData() + # then create some tokens + cls.token = Token( + camp=cls.camp, + token="DEADBEAF1234", + description="Test token", + category="Test", + active=True, + ) + cls.token.save() + + def test_token_list_view(self) -> None: + """Test the basics of the token list view.""" + self.client.login(username="user0", password="user0") + url = reverse("tokens:tokenfind_list") + + response = self.client.get(url) + content = response.content.decode() + soup = BeautifulSoup(content, "html.parser") + rows = soup.select("div#main > div > div > div > div > table > tbody > tr") + self.assertEqual(len(rows), 3, "token list does not return 3 entries (camp name, header and token)") + + def test_token_find_view(self) -> None: + """Test the basics of the token find view.""" + self.client.login(username="user0", password="user0") + + url = reverse("tokens:details", kwargs={"token": self.token.token}) + + # Test finding the test token + response = self.client.get(path=url, follow=True) + assert response.status_code == 200 + + # Test if the page returned a success + content = response.content.decode() + soup = BeautifulSoup(content, "html.parser") + rows = soup.select("div.alert.alert-success") + matches = [s for s in rows if "You found a secret token:" in str(s)] + self.assertEqual(len(matches), 1, "token_find failed") + diff --git a/src/tokens/urls.py b/src/tokens/urls.py index 29f4931e3..dcb0fbaff 100644 --- a/src/tokens/urls.py +++ b/src/tokens/urls.py @@ -1,3 +1,4 @@ +"""All URLs for the Token application.""" from __future__ import annotations from django.urls import path diff --git a/src/tokens/views.py b/src/tokens/views.py index 135bb4b99..fb779757e 100644 --- a/src/tokens/views.py +++ b/src/tokens/views.py @@ -1,5 +1,8 @@ +"""All views for the Token application.""" from __future__ import annotations +from typing import TYPE_CHECKING + from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.http import Http404 @@ -10,6 +13,11 @@ from django.views.generic import ListView from prometheus_client import Gauge +if TYPE_CHECKING: + from django.db.models import QuerySet + from django.http import HttpRequest + from django.http import HttpResponsePermanentRedirect + from utils.models import CampReadOnlyModeError from .models import Token @@ -28,11 +36,13 @@ class TokenFindView(LoginRequiredMixin, DetailView): + """View for submitting the token found.""" model = Token slug_field = "token" slug_url_kwarg = "token" - def get(self, request, *args, **kwargs): + def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponsePermanentRedirect: + """Method for submitting the token found.""" if not self.get_object().active: messages.warning( self.request, @@ -61,8 +71,8 @@ def get(self, request, *args, **kwargs): token=self.get_object(), user=request.user, ) - except CampReadOnlyModeError: - raise Http404 + except CampReadOnlyModeError as e: + raise Http404 from e if created: # user found a new token @@ -89,15 +99,18 @@ def get(self, request, *args, **kwargs): # message for the user messages.success( self.request, - f"Congratulations! You found a secret token: '{self.get_object().description}' - Your visit has been registered! Keep hunting, there might be more tokens out there.", + f"Congratulations! You found a secret token: '{self.get_object().description}' " + "- Your visit has been registered! Keep hunting, there might be more tokens out there.", ) return redirect(reverse("tokens:tokenfind_list")) class TokenFindListView(LoginRequiredMixin, ListView): + """A View with a list of active tokens one can find.""" model = Token template_name = "tokenfind_list.html" - def get_queryset(self): + def get_queryset(self) -> QuerySet: + """Get QuerySet of active tokens.""" qs = super().get_queryset() return qs.filter(active=True) From 8723d5ef1347f1865fd4c6e54a53ed4cdc294013 Mon Sep 17 00:00:00 2001 From: "Rudy (zarya)" Date: Tue, 13 May 2025 20:54:01 +0200 Subject: [PATCH 2/9] Added test for non-excisting token --- src/tokens/models.py | 4 ++-- src/tokens/tests/test_views.py | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/tokens/models.py b/src/tokens/models.py index 21bb3c35d..06a9916e4 100644 --- a/src/tokens/models.py +++ b/src/tokens/models.py @@ -17,7 +17,7 @@ from camps.models import Camp class Token(ExportModelOperationsMixin("token"), CampRelatedModel): - """Secret Token model.""" + """Token model.""" camp = models.ForeignKey("camps.Camp", on_delete=models.PROTECT) token = models.CharField(max_length=32, help_text="The secret token") @@ -76,7 +76,7 @@ def valid_now(self) -> bool: class TokenFind(ExportModelOperationsMixin("token_find"), CampRelatedModel): - """Model with all found Secret Tokens.""" + """Model for submitting the found token.""" class Meta: """Meta.""" unique_together = ("user", "token") diff --git a/src/tokens/tests/test_views.py b/src/tokens/tests/test_views.py index 085313444..36ae948f5 100644 --- a/src/tokens/tests/test_views.py +++ b/src/tokens/tests/test_views.py @@ -57,3 +57,8 @@ def test_token_find_view(self) -> None: matches = [s for s in rows if "You found a secret token:" in str(s)] self.assertEqual(len(matches), 1, "token_find failed") + # Test finding a false token + url = reverse("tokens:details", kwargs={"token": "F00000001234"}) + response = self.client.get(path=url, follow=True) + self.assertEqual(response.status_code, 404, "Did not find a non-excisting token") + From ce70ff5f0c1e92427537485a5b7a305a12e9b81a Mon Sep 17 00:00:00 2001 From: "Rudy (zarya)" Date: Tue, 13 May 2025 20:59:52 +0200 Subject: [PATCH 3/9] More linting --- src/tokens/admin.py | 3 +++ src/tokens/apps.py | 2 ++ src/tokens/models.py | 6 ++++++ src/tokens/tests/test_views.py | 1 - src/tokens/urls.py | 1 + src/tokens/views.py | 3 +++ 6 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/tokens/admin.py b/src/tokens/admin.py index 0445a9e73..f6c3355d7 100644 --- a/src/tokens/admin.py +++ b/src/tokens/admin.py @@ -1,4 +1,5 @@ """All Django admin views for application token.""" + from __future__ import annotations from typing import TYPE_CHECKING @@ -15,6 +16,7 @@ @admin.register(Token) class TokenAdmin(admin.ModelAdmin): """Django admin for tokens.""" + list_filter: ClassVar[list[str]] = ["camp", "category", "active"] list_display: ClassVar[list[str]] = ["token", "description", "camp", "category", "active", "valid_when"] search_fields: ClassVar[list[str]] = ["token", "description", "category"] @@ -23,6 +25,7 @@ class TokenAdmin(admin.ModelAdmin): @admin.register(TokenFind) class TokenFindAdmin(admin.ModelAdmin): """Django admin for token finds.""" + list_filter: ClassVar[list[str]] = ["token__camp", "user"] list_display: ClassVar[list[str]] = ["token", "user", "created"] search_fields: ClassVar[list[str]] = ["user", "token"] diff --git a/src/tokens/apps.py b/src/tokens/apps.py index 3901ad513..d8db00707 100644 --- a/src/tokens/apps.py +++ b/src/tokens/apps.py @@ -1,4 +1,5 @@ """All apps for token application.""" + from __future__ import annotations from django.apps import AppConfig @@ -6,4 +7,5 @@ class TokensConfig(AppConfig): """TokensConfig.""" + name = "tokens" diff --git a/src/tokens/models.py b/src/tokens/models.py index 06a9916e4..078731712 100644 --- a/src/tokens/models.py +++ b/src/tokens/models.py @@ -1,4 +1,5 @@ """All models for the token application.""" + from __future__ import annotations from typing import TYPE_CHECKING @@ -16,8 +17,10 @@ from camps.models import Camp + class Token(ExportModelOperationsMixin("token"), CampRelatedModel): """Token model.""" + camp = models.ForeignKey("camps.Camp", on_delete=models.PROTECT) token = models.CharField(max_length=32, help_text="The secret token") @@ -50,6 +53,7 @@ def __str__(self) -> str: class Meta: """Meta.""" + ordering: ClassVar[list[str]] = ["camp"] def get_absolute_url(self) -> str: @@ -77,8 +81,10 @@ def valid_now(self) -> bool: class TokenFind(ExportModelOperationsMixin("token_find"), CampRelatedModel): """Model for submitting the found token.""" + class Meta: """Meta.""" + unique_together = ("user", "token") token = models.ForeignKey("tokens.Token", on_delete=models.PROTECT) diff --git a/src/tokens/tests/test_views.py b/src/tokens/tests/test_views.py index 36ae948f5..bad833f2d 100644 --- a/src/tokens/tests/test_views.py +++ b/src/tokens/tests/test_views.py @@ -61,4 +61,3 @@ def test_token_find_view(self) -> None: url = reverse("tokens:details", kwargs={"token": "F00000001234"}) response = self.client.get(path=url, follow=True) self.assertEqual(response.status_code, 404, "Did not find a non-excisting token") - diff --git a/src/tokens/urls.py b/src/tokens/urls.py index dcb0fbaff..495bdfb50 100644 --- a/src/tokens/urls.py +++ b/src/tokens/urls.py @@ -1,4 +1,5 @@ """All URLs for the Token application.""" + from __future__ import annotations from django.urls import path diff --git a/src/tokens/views.py b/src/tokens/views.py index fb779757e..1debdb4a0 100644 --- a/src/tokens/views.py +++ b/src/tokens/views.py @@ -1,4 +1,5 @@ """All views for the Token application.""" + from __future__ import annotations from typing import TYPE_CHECKING @@ -37,6 +38,7 @@ class TokenFindView(LoginRequiredMixin, DetailView): """View for submitting the token found.""" + model = Token slug_field = "token" slug_url_kwarg = "token" @@ -107,6 +109,7 @@ def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponsePermanentRed class TokenFindListView(LoginRequiredMixin, ListView): """A View with a list of active tokens one can find.""" + model = Token template_name = "tokenfind_list.html" From 6e8a3b3ad37cc709dd2d7b835bbd343a6c7bb18b Mon Sep 17 00:00:00 2001 From: "Rudy (zarya)" Date: Tue, 13 May 2025 21:48:15 +0200 Subject: [PATCH 4/9] Added more tests --- src/tokens/tests/test_views.py | 104 ++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/src/tokens/tests/test_views.py b/src/tokens/tests/test_views.py index bad833f2d..a0863a435 100644 --- a/src/tokens/tests/test_views.py +++ b/src/tokens/tests/test_views.py @@ -2,6 +2,9 @@ from __future__ import annotations +from datetime import datetime + +import pytz from bs4 import BeautifulSoup from django.urls import reverse @@ -13,12 +16,22 @@ class TestTokenViews(BornhackTestBase): """Test Phonebook view.""" token: Token + token_inactive: Token + token_timed: Token + token_timed_old: Token + token_timed_current: Token + token_timed_new: Token @classmethod def setUpTestData(cls) -> None: """Add test data.""" # first add users and other basics super().setUpTestData() + + tz = pytz.timezone("Europe/Copenhagen") + now = datetime.now(tz) + year = now.year + # then create some tokens cls.token = Token( camp=cls.camp, @@ -29,6 +42,45 @@ def setUpTestData(cls) -> None: ) cls.token.save() + cls.token_inactive = Token( + camp=cls.camp, + token="1234DEADBEAF", + description="Test Inactive token", + category="Test", + active=False, + ) + cls.token_inactive.save() + + cls.token_timed_old = Token( + camp=cls.camp, + token="12341337F01F", + description="Test timed token", + category="Test", + active=True, + valid_when=["2000-01-01 00:00:00", "2000-10-10 10:10:10"], + ) + cls.token_timed_old.save() + + cls.token_timed_current = Token( + camp=cls.camp, + token="12341337F02F", + description="Test timed token", + category="Test", + active=True, + valid_when=[now, datetime(year + 1, 1, 1, 1, 1, tzinfo=tz)], + ) + cls.token_timed_current.save() + + cls.token_timed_new = Token( + camp=cls.camp, + token="12341337F03F", + description="Test timed token", + category="Test", + active=True, + valid_when=[datetime(year + 1, 1, 1, 1, 1, tzinfo=tz), datetime(year + 1, 12, 1, 1, 1, tzinfo=tz)], + ) + cls.token_timed_new.save() + def test_token_list_view(self) -> None: """Test the basics of the token list view.""" self.client.login(username="user0", password="user0") @@ -38,7 +90,7 @@ def test_token_list_view(self) -> None: content = response.content.decode() soup = BeautifulSoup(content, "html.parser") rows = soup.select("div#main > div > div > div > div > table > tbody > tr") - self.assertEqual(len(rows), 3, "token list does not return 3 entries (camp name, header and token)") + self.assertEqual(len(rows), 6, "token list does not return 6 entries (camp name, header and tokens)") def test_token_find_view(self) -> None: """Test the basics of the token find view.""" @@ -55,9 +107,57 @@ def test_token_find_view(self) -> None: soup = BeautifulSoup(content, "html.parser") rows = soup.select("div.alert.alert-success") matches = [s for s in rows if "You found a secret token:" in str(s)] - self.assertEqual(len(matches), 1, "token_find failed") + self.assertEqual(len(matches), 1, "token find does not return the found msg.") # Test finding a false token url = reverse("tokens:details", kwargs={"token": "F00000001234"}) response = self.client.get(path=url, follow=True) self.assertEqual(response.status_code, 404, "Did not find a non-excisting token") + + # Test finding a inactive token + url = reverse("tokens:details", kwargs={"token": self.token_inactive.token}) + response = self.client.get(path=url, follow=True) + assert response.status_code == 200 + + # Test if the page returned a warning + content = response.content.decode() + soup = BeautifulSoup(content, "html.parser") + rows = soup.select("div.alert.alert-warning") + matches = [s for s in rows if "Patience!" in str(s)] + self.assertEqual(len(matches), 1, "inactive token find does not return the Patience msg.") + + # Test finding a time expired token + url = reverse("tokens:details", kwargs={"token": self.token_timed_old.token}) + response = self.client.get(path=url, follow=True) + assert response.status_code == 200 + + # Test if the page returned a warning + content = response.content.decode() + soup = BeautifulSoup(content, "html.parser") + rows = soup.select("div.alert.alert-warning") + matches = [s for s in rows if "This token is not valid after" in str(s)] + self.assertEqual(len(matches), 1, "inactive token find does not return the not valid after msg.") + + # Test finding a timed token + url = reverse("tokens:details", kwargs={"token": self.token_timed_current.token}) + response = self.client.get(path=url, follow=True) + assert response.status_code == 200 + + # Test if the page returned a success + content = response.content.decode() + soup = BeautifulSoup(content, "html.parser") + rows = soup.select("div.alert.alert-success") + matches = [s for s in rows if "You found a secret token:" in str(s)] + self.assertEqual(len(matches), 1, "token find does not return the found msg.") + + # Test finding a timed not active yet token + url = reverse("tokens:details", kwargs={"token": self.token_timed_new.token}) + response = self.client.get(path=url, follow=True) + assert response.status_code == 200 + + # Test if the page returned a warning + content = response.content.decode() + soup = BeautifulSoup(content, "html.parser") + rows = soup.select("div.alert.alert-warning") + matches = [s for s in rows if "This token is not valid yet" in str(s)] + self.assertEqual(len(matches), 1, "inactive token find does not return the not valid yet.") From 30d499511a53aa5a8e29014127809856dd9a3d4b Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Wed, 14 May 2025 06:49:33 +0200 Subject: [PATCH 5/9] Update src/tokens/tests/test_views.py --- src/tokens/tests/test_views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tokens/tests/test_views.py b/src/tokens/tests/test_views.py index a0863a435..b29d9ed15 100644 --- a/src/tokens/tests/test_views.py +++ b/src/tokens/tests/test_views.py @@ -13,7 +13,7 @@ class TestTokenViews(BornhackTestBase): - """Test Phonebook view.""" + """Test Token view.""" token: Token token_inactive: Token From 35a1e32e4d574c3b23e801be7faf377bb4735d1c Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Wed, 14 May 2025 06:51:59 +0200 Subject: [PATCH 6/9] Update src/tokens/tests/test_views.py --- src/tokens/tests/test_views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tokens/tests/test_views.py b/src/tokens/tests/test_views.py index b29d9ed15..9b2e91bdb 100644 --- a/src/tokens/tests/test_views.py +++ b/src/tokens/tests/test_views.py @@ -112,7 +112,7 @@ def test_token_find_view(self) -> None: # Test finding a false token url = reverse("tokens:details", kwargs={"token": "F00000001234"}) response = self.client.get(path=url, follow=True) - self.assertEqual(response.status_code, 404, "Did not find a non-excisting token") + self.assertEqual(response.status_code, 404, "Did not find a non-existing token") # Test finding a inactive token url = reverse("tokens:details", kwargs={"token": self.token_inactive.token}) From a007b564c97f050fdd8f281bea9974ca1c928c58 Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Wed, 14 May 2025 06:52:34 +0200 Subject: [PATCH 7/9] Update src/tokens/tests/test_views.py --- src/tokens/tests/test_views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tokens/tests/test_views.py b/src/tokens/tests/test_views.py index 9b2e91bdb..f96aeda6c 100644 --- a/src/tokens/tests/test_views.py +++ b/src/tokens/tests/test_views.py @@ -112,7 +112,7 @@ def test_token_find_view(self) -> None: # Test finding a false token url = reverse("tokens:details", kwargs={"token": "F00000001234"}) response = self.client.get(path=url, follow=True) - self.assertEqual(response.status_code, 404, "Did not find a non-existing token") + self.assertEqual(response.status_code, 404, "Did not get 404 for a non-existing token") # Test finding a inactive token url = reverse("tokens:details", kwargs={"token": self.token_inactive.token}) From 415a743073c89f093a705e2096d7b898bdf8010d Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Wed, 14 May 2025 06:56:57 +0200 Subject: [PATCH 8/9] Update src/tokens/views.py --- src/tokens/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tokens/views.py b/src/tokens/views.py index 1debdb4a0..c3414c655 100644 --- a/src/tokens/views.py +++ b/src/tokens/views.py @@ -17,7 +17,7 @@ if TYPE_CHECKING: from django.db.models import QuerySet from django.http import HttpRequest - from django.http import HttpResponsePermanentRedirect + from django.http import HttpResponseRedirect from utils.models import CampReadOnlyModeError From 1dabf5b2d19b9e818da68781d30df714184a712b Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Wed, 14 May 2025 06:57:20 +0200 Subject: [PATCH 9/9] Update src/tokens/views.py --- src/tokens/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tokens/views.py b/src/tokens/views.py index c3414c655..4fa02b858 100644 --- a/src/tokens/views.py +++ b/src/tokens/views.py @@ -43,7 +43,7 @@ class TokenFindView(LoginRequiredMixin, DetailView): slug_field = "token" slug_url_kwarg = "token" - def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponsePermanentRedirect: + def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponseRedirect: """Method for submitting the token found.""" if not self.get_object().active: messages.warning(