major navbar overhaul: .btn-primary.btn-xl now reads CONT GAME and links to the user's most recently active game; log out functionality transferred to new BYE .btn-abandon abutting login spans; tooltips for each asserted via new FTs.test_navbar methods to appear w.in visible area
This commit is contained in:
@@ -1,4 +1,30 @@
|
||||
def user_palette(request):
|
||||
if request.user.is_authenticated:
|
||||
return {"user_palette": request.user.palette}
|
||||
return {"user_palette": "palette-default"}
|
||||
return {"user_palette": "palette-default"}
|
||||
|
||||
|
||||
def navbar_context(request):
|
||||
if not request.user.is_authenticated:
|
||||
return {}
|
||||
from django.db.models import Max, Q
|
||||
from django.urls import reverse
|
||||
from apps.epic.models import Room
|
||||
|
||||
recent_room = (
|
||||
Room.objects.filter(
|
||||
Q(owner=request.user) | Q(gate_slots__gamer=request.user)
|
||||
)
|
||||
.annotate(last_event=Max("events__timestamp"))
|
||||
.filter(last_event__isnull=False)
|
||||
.order_by("-last_event")
|
||||
.distinct()
|
||||
.first()
|
||||
)
|
||||
if recent_room is None:
|
||||
return {}
|
||||
if recent_room.table_status:
|
||||
url = reverse("epic:room", args=[recent_room.id])
|
||||
else:
|
||||
url = reverse("epic:gatekeeper", args=[recent_room.id])
|
||||
return {"navbar_recent_room_url": url}
|
||||
@@ -102,6 +102,7 @@ TEMPLATES = [
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'core.context_processors.user_palette',
|
||||
'core.context_processors.navbar_context',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
109
src/core/tests/unit/test_context_processors.py
Normal file
109
src/core/tests/unit/test_context_processors.py
Normal file
@@ -0,0 +1,109 @@
|
||||
from datetime import timedelta
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from django.test import TestCase, RequestFactory
|
||||
from django.utils import timezone
|
||||
|
||||
from apps.drama.models import GameEvent, record
|
||||
from apps.epic.models import Room
|
||||
from apps.lyric.models import User
|
||||
|
||||
from core.context_processors import navbar_context
|
||||
|
||||
|
||||
class NavbarContextProcessorTest(TestCase):
|
||||
def setUp(self):
|
||||
self.factory = RequestFactory()
|
||||
|
||||
def _anon_request(self):
|
||||
req = self.factory.get("/")
|
||||
req.user = MagicMock(is_authenticated=False)
|
||||
return req
|
||||
|
||||
def _auth_request(self, user):
|
||||
req = self.factory.get("/")
|
||||
req.user = user
|
||||
return req
|
||||
|
||||
def _room_with_event(self, owner, name="Test Room"):
|
||||
room = Room.objects.create(name=name, owner=owner)
|
||||
record(
|
||||
room, GameEvent.SLOT_FILLED, actor=owner,
|
||||
slot_number=1, token_type="coin",
|
||||
token_display="Coin-on-a-String", renewal_days=7,
|
||||
)
|
||||
return room
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Anonymous user #
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
def test_returns_empty_for_anonymous_user(self):
|
||||
ctx = navbar_context(self._anon_request())
|
||||
self.assertEqual(ctx, {})
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Authenticated user — no rooms #
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
def test_returns_empty_when_no_rooms_with_events(self):
|
||||
user = User.objects.create(email="disco@test.io")
|
||||
# Room exists but has no events
|
||||
Room.objects.create(name="Empty Room", owner=user)
|
||||
|
||||
ctx = navbar_context(self._auth_request(user))
|
||||
self.assertEqual(ctx, {})
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Room in gate phase (no table_status) → gatekeeper URL #
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
def test_returns_gatekeeper_url_for_gate_phase_room(self):
|
||||
user = User.objects.create(email="disco@test.io")
|
||||
room = self._room_with_event(user)
|
||||
|
||||
ctx = navbar_context(self._auth_request(user))
|
||||
self.assertIn("navbar_recent_room_url", ctx)
|
||||
self.assertIn(str(room.id), ctx["navbar_recent_room_url"])
|
||||
self.assertIn("gate", ctx["navbar_recent_room_url"])
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Room in role-select (table_status set) → room view URL #
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
def test_returns_room_url_for_table_status_room(self):
|
||||
user = User.objects.create(email="disco@test.io")
|
||||
room = self._room_with_event(user)
|
||||
room.table_status = Room.ROLE_SELECT
|
||||
room.save()
|
||||
|
||||
ctx = navbar_context(self._auth_request(user))
|
||||
self.assertIn("navbar_recent_room_url", ctx)
|
||||
self.assertIn(str(room.id), ctx["navbar_recent_room_url"])
|
||||
self.assertNotIn("gate", ctx["navbar_recent_room_url"])
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Most recently updated room is chosen #
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
def test_returns_most_recently_updated_room(self):
|
||||
user = User.objects.create(email="disco@test.io")
|
||||
older_room = self._room_with_event(user, name="Older Room")
|
||||
newer_room = self._room_with_event(user, name="Newer Room")
|
||||
|
||||
ctx = navbar_context(self._auth_request(user))
|
||||
self.assertIn(str(newer_room.id), ctx["navbar_recent_room_url"])
|
||||
self.assertNotIn(str(older_room.id), ctx["navbar_recent_room_url"])
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# User sees own rooms but not others' rooms they never joined #
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
def test_ignores_rooms_user_has_no_connection_to(self):
|
||||
owner = User.objects.create(email="owner@test.io")
|
||||
other = User.objects.create(email="other@test.io")
|
||||
# Create a room belonging only to `owner`
|
||||
self._room_with_event(owner)
|
||||
|
||||
ctx = navbar_context(self._auth_request(other))
|
||||
self.assertEqual(ctx, {})
|
||||
Reference in New Issue
Block a user