From 51defc11e1c781e1a9936eea85fca0be7111d591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Hells=C3=A9n?= Date: Sat, 9 May 2026 22:53:29 +0200 Subject: [PATCH] Fix categoryless campaigns not making template work --- kick/tests/test_kick.py | 74 +++++++++++++++++++++++++++++ templates/kick/campaign_detail.html | 18 ++++--- templates/kick/campaign_list.html | 6 ++- templates/kick/dashboard.html | 14 ++++-- 4 files changed, 100 insertions(+), 12 deletions(-) diff --git a/kick/tests/test_kick.py b/kick/tests/test_kick.py index 142fab4..d404ccd 100644 --- a/kick/tests/test_kick.py +++ b/kick/tests/test_kick.py @@ -679,6 +679,34 @@ class KickDashboardViewTest(TestCase): ) assert campaign.name in response.content.decode() + def test_dashboard_handles_campaign_without_category(self) -> None: + """Dashboard should render active campaigns with no category.""" + org: KickOrganization = KickOrganization.objects.create( + kick_id="org-view-no-category", + name="Org No Category", + ) + campaign: KickDropCampaign = KickDropCampaign.objects.create( + kick_id="camp-view-no-category", + name="Active No Category Campaign", + status="active", + starts_at=dt(2020, 1, 1, tzinfo=UTC), + ends_at=dt(2099, 12, 31, tzinfo=UTC), + organization=org, + category=None, + rule_id=1, + rule_name="Watch to redeem", + is_fully_imported=True, + ) + + response: _MonkeyPatchedWSGIResponse = self.client.get( + reverse("kick:dashboard"), + ) + + content: str = response.content.decode() + assert response.status_code == 200 + assert campaign.name in content + assert "Unknown game" in content + def test_dashboard_query_count_stays_flat_with_more_campaigns(self) -> None: """Dashboard SELECT query count should stay flat as active campaign count grows.""" @@ -823,6 +851,30 @@ class KickCampaignListViewTest(TestCase): ) assert campaign.name in response.content.decode() + def test_campaign_list_handles_campaign_without_category(self) -> None: + """Campaign list should render campaigns with no category.""" + campaign: KickDropCampaign = KickDropCampaign.objects.create( + kick_id="camp-list-no-category", + name="List No Category Campaign", + status="active", + starts_at=dt(2020, 1, 1, tzinfo=UTC), + ends_at=dt(2099, 12, 31, tzinfo=UTC), + organization=self.org, + category=None, + rule_id=1, + rule_name="Watch to redeem", + is_fully_imported=True, + ) + + response: _MonkeyPatchedWSGIResponse = self.client.get( + reverse("kick:campaign_list"), + ) + + content: str = response.content.decode() + assert response.status_code == 200 + assert campaign.name in content + assert "Unknown game" in content + def test_campaign_list_status_filter(self) -> None: """Filtering by status should show only campaigns with that status.""" active: KickDropCampaign = self._make_campaign( @@ -886,6 +938,28 @@ class KickCampaignDetailViewTest(TestCase): ) assert campaign.name in response.content.decode() + def test_campaign_detail_handles_campaign_without_category(self) -> None: + """Campaign detail should render campaigns with no category.""" + org: KickOrganization = KickOrganization.objects.create( + kick_id="org-det-no-category", + name="Detail Org No Category", + ) + campaign: KickDropCampaign = KickDropCampaign.objects.create( + kick_id="camp-det-no-category", + name="Detail No Category Campaign", + organization=org, + category=None, + rule_id=1, + rule_name="Watch to redeem", + ) + + response: _MonkeyPatchedWSGIResponse = self.client.get( + reverse("kick:campaign_detail", kwargs={"kick_id": campaign.kick_id}), + ) + + assert response.status_code == 200 + assert campaign.name in response.content.decode() + def test_campaign_detail_404_for_unknown(self) -> None: """Campaign detail view should return HTTP 404 status code for unknown campaign.""" response: _MonkeyPatchedWSGIResponse = self.client.get( diff --git a/templates/kick/campaign_detail.html b/templates/kick/campaign_detail.html index b93cb98..524607a 100644 --- a/templates/kick/campaign_detail.html +++ b/templates/kick/campaign_detail.html @@ -136,12 +136,14 @@

{% endif %}
- [rss] - [atom] - [discord] + {% if campaign.category %} + [rss] + [atom] + [discord] + {% endif %} [explain] {% if campaign.connect_url %} [about]{% endif %} {% if campaign.channels.count == 0 %} - {% if campaign.rule_name == "Watch to redeem" %}[watch]{% endif %} + {% if campaign.category and campaign.rule_name == "Watch to redeem" %} + [watch] + {% endif %} {% endif %}
diff --git a/templates/kick/campaign_list.html b/templates/kick/campaign_list.html index 6af7660..10a6bee 100644 --- a/templates/kick/campaign_list.html +++ b/templates/kick/campaign_list.html @@ -77,7 +77,11 @@ {{ campaign.name }} - {{ campaign.category.name }} + {% if campaign.category %} + {{ campaign.category.name }} + {% else %} + Unknown game + {% endif %} {{ campaign.organization.name }} diff --git a/templates/kick/dashboard.html b/templates/kick/dashboard.html index 4f4732f..483652d 100644 --- a/templates/kick/dashboard.html +++ b/templates/kick/dashboard.html @@ -39,7 +39,11 @@

- {{ campaign.category.name }} + {% if campaign.category %} + {{ campaign.category.name }} + {% else %} + Unknown game + {% endif %}

{% if campaign.organization %} @@ -138,9 +142,11 @@ {% endif %} {% else %} -

- {{ campaign.category.name }} is game wide. -

+ {% if campaign.category %} +

+ {{ campaign.category.name }} is game wide. +

+ {% endif %} {% endif %}
{% if campaign.merged_rewards %}