from __future__ import annotations import os from datetime import UTC from datetime import datetime from typing import TYPE_CHECKING import pytest from django.conf import settings from django.test import TestCase from django.urls import reverse from twitch import sitemaps from twitch.models import Channel from twitch.models import ChatBadgeSet from twitch.models import DropCampaign from twitch.models import Game from twitch.models import Organization from twitch.models import RewardCampaign if TYPE_CHECKING: from pathlib import Path class SitemapTests(TestCase): """Tests for Twitch sitemaps.""" def test_static_view_sitemap_items_and_location(self) -> None: """Test that StaticViewSitemap returns expected items and correct locations.""" sitemap = sitemaps.TwitchSitemapGenerator() items: list[str] = sitemap.items() expected: list[str] = [ "twitch:dashboard", "twitch:campaign_list", "twitch:reward_campaign_list", "twitch:games_grid", "twitch:games_list", "twitch:org_list", "twitch:channel_list", "twitch:badge_list", "twitch:emote_gallery", "twitch:search", # the two items below were added later and need coverage "twitch:dataset_backups", "twitch:docs_rss", ] assert set(items) == set(expected) for name in items: assert sitemap.location(name) == reverse(name) def test_game_sitemap_items_and_location(self) -> None: """Test that GameSitemap returns expected items and correct locations.""" game: Game = Game.objects.create(twitch_id="g-1", display_name="Test Game") sitemap = sitemaps.GameSitemap() items: list[Game] = list(sitemap.items()) assert game in items assert sitemap.location(game) == reverse("twitch:game_detail", args=[game.twitch_id]) org: Organization = Organization.objects.create(twitch_id="o-1", name="Org One") channel: Channel = Channel.objects.create(twitch_id="c-1", name="chan", display_name="Chan One") badge_set: ChatBadgeSet = ChatBadgeSet.objects.create(set_id="b-1") game: Game = Game.objects.create(twitch_id="g-2", display_name="Game Two") campaign: DropCampaign = DropCampaign.objects.create(twitch_id="dc-1", name="Campaign One", game=game) reward: RewardCampaign = RewardCampaign.objects.create(twitch_id="rc-1", name="Reward One") campaign_sitemap = sitemaps.CampaignSitemap() assert campaign in list(campaign_sitemap.items()) assert campaign_sitemap.location(campaign) == reverse("twitch:campaign_detail", args=[campaign.twitch_id]) org_sitemap = sitemaps.OrganizationSitemap() assert org in list(org_sitemap.items()) assert org_sitemap.location(org) == reverse("twitch:organization_detail", args=[org.twitch_id]) channel_sitemap = sitemaps.ChannelSitemap() assert channel in list(channel_sitemap.items()) assert channel_sitemap.location(channel) == reverse("twitch:channel_detail", args=[channel.twitch_id]) badge_sitemap = sitemaps.BadgeSitemap() assert badge_set in list(badge_sitemap.items()) assert badge_sitemap.location(badge_set) == reverse("twitch:badge_set_detail", args=[badge_set.set_id]) reward_sitemap = sitemaps.RewardCampaignSitemap() assert reward in list(reward_sitemap.items()) assert reward_sitemap.location(reward) == reverse("twitch:reward_campaign_detail", args=[reward.twitch_id]) @pytest.mark.django_db def test_static_view_lastmod_behavior(tmp_path: sitemaps.Path, monkeypatch: pytest.MonkeyPatch) -> None: """Standalone pytest test for :meth:`TwitchSitemapGenerator.lastmod`. We exercise both the docs RSS branch (which should always return ``None``) and the dataset backups branch, including scenarios with and without backup files present. """ sitemap = sitemaps.TwitchSitemapGenerator() assert sitemap.lastmod("twitch:docs_rss") is None monkeypatch.setattr(settings, "DATA_DIR", tmp_path) assert sitemap.lastmod("twitch:dataset_backups") is None datasets: Path = tmp_path / "datasets" datasets.mkdir() older: Path = datasets / "dataset_backup_old.zip" newer: Path = datasets / "dataset_backup_new.zip" older.write_text("old", encoding="utf-8") newer.write_text("new", encoding="utf-8") os.utime(older, (1_000, 1_000)) os.utime(newer, (2_000, 2_000)) expected: datetime = datetime.fromtimestamp(2_000, tz=UTC) assert sitemap.lastmod("twitch:dataset_backups") == expected