feat(game-detail): link sections to filtered lists (#66)
Add "View all" links to the Purchases / Sessions / Play Events sections on the game-detail page, each pointing at the matching filtered list view via filter_url(). Pure consumer of the #56 filter_url()/where() helpers; no new filter machinery. - _game_section() gains an optional view_all_url, rendered as a gray xs button beside the heading (shown only when the section is non-empty). - New arrowright icon for the link. - Tests: each section renders the expected escaped href; a parity test asserts each link's filter scopes to the game and excludes others. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
"""Rendering tests: game-detail sections wire "View all" links to filtered lists (#66)."""
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import pytest
|
||||
from django.utils.html import escape
|
||||
|
||||
from games.filters import (
|
||||
PlayEventFilter,
|
||||
PurchaseFilter,
|
||||
SessionFilter,
|
||||
filter_url,
|
||||
)
|
||||
from games.models import Game, Platform, PlayEvent, Purchase, Session
|
||||
from games.views.game import view_game
|
||||
|
||||
|
||||
def _dt(day, hour=12):
|
||||
return datetime(2024, 6, day, hour, 0, tzinfo=timezone.utc)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def game(db):
|
||||
platform = Platform.objects.create(name="PC")
|
||||
game = Game.objects.create(
|
||||
name="Test Game", platform=platform, status=Game.Status.PLAYED
|
||||
)
|
||||
Session.objects.create(game=game, timestamp_start=_dt(1), timestamp_end=_dt(1, 13))
|
||||
Purchase.objects.create(date_purchased=_dt(1), type=Purchase.GAME).games.set([game])
|
||||
PlayEvent.objects.create(game=game, ended=_dt(2))
|
||||
return game
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def rendered(game, rf, django_user_model):
|
||||
user = django_user_model.objects.create_user(username="u", password="p")
|
||||
request = rf.get(f"/game/{game.id}/")
|
||||
request.user = user
|
||||
request.session = {}
|
||||
return view_game(request, game.id).content.decode()
|
||||
|
||||
|
||||
def test_sessions_section_links_to_filtered_sessions(game, rendered):
|
||||
href = escape(filter_url(SessionFilter.where(game=[game.id])))
|
||||
assert href in rendered
|
||||
|
||||
|
||||
def test_purchases_section_links_to_filtered_purchases(game, rendered):
|
||||
href = escape(filter_url(PurchaseFilter.where(games=[game.id])))
|
||||
assert href in rendered
|
||||
|
||||
|
||||
def test_playevents_section_links_to_filtered_playevents(game, rendered):
|
||||
href = escape(filter_url(PlayEventFilter.where(game=[game.id])))
|
||||
assert href in rendered
|
||||
|
||||
|
||||
def test_link_filters_scope_to_game(game):
|
||||
"""Each link's filter selects exactly the game's own records, not another
|
||||
game's (parity between the section and the filtered list it links to)."""
|
||||
other = Game.objects.create(name="Other", platform=game.platform)
|
||||
Session.objects.create(game=other, timestamp_start=_dt(3), timestamp_end=_dt(3, 13))
|
||||
Purchase.objects.create(date_purchased=_dt(3), type=Purchase.GAME).games.set(
|
||||
[other]
|
||||
)
|
||||
PlayEvent.objects.create(game=other, ended=_dt(4))
|
||||
|
||||
sessions = Session.objects.filter(SessionFilter.where(game=[game.id]).to_q())
|
||||
assert list(sessions) == list(game.sessions.all())
|
||||
|
||||
purchases = Purchase.objects.filter(PurchaseFilter.where(games=[game.id]).to_q())
|
||||
assert list(purchases) == list(game.purchases.all())
|
||||
|
||||
playevents = PlayEvent.objects.filter(PlayEventFilter.where(game=[game.id]).to_q())
|
||||
assert list(playevents) == list(game.playevents.all())
|
||||
|
||||
|
||||
def test_no_view_all_for_empty_section(db, django_user_model, rf):
|
||||
"""A game with no sessions/purchases/playevents shows no 'View all' link."""
|
||||
platform = Platform.objects.create(name="PC")
|
||||
empty_game = Game.objects.create(name="Empty", platform=platform)
|
||||
user = django_user_model.objects.create_user(username="u2", password="p")
|
||||
request = rf.get(f"/game/{empty_game.id}/")
|
||||
request.user = user
|
||||
request.session = {}
|
||||
html = view_game(request, empty_game.id).content.decode()
|
||||
assert "View all" not in html
|
||||
Reference in New Issue
Block a user