Files
timetracker/tests/test_game_detail_links.py
T
lukas 3828bfb9ef 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>
2026-06-21 18:24:40 +02:00

88 lines
3.1 KiB
Python

"""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