Suppress xml.etree security lint for sitemap test
Add explicit noqa comments for S405/S314 in core/tests/test_sitemaps.py to satisfy the linter in test context. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
1161670c34
commit
778f71320f
2 changed files with 125 additions and 7 deletions
73
core/tests/test_sitemaps.py
Normal file
73
core/tests/test_sitemaps.py
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import xml.etree.ElementTree as ET # noqa: S405
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from django.urls import reverse
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from django.test.client import Client
|
||||
|
||||
|
||||
def _extract_locs(xml_bytes: bytes) -> list[str]:
|
||||
root = ET.fromstring(xml_bytes) # noqa: S314
|
||||
ns = {"s": "http://www.sitemaps.org/schemas/sitemap/0.9"}
|
||||
return [el.text for el in root.findall(".//s:loc", ns) if el.text]
|
||||
|
||||
|
||||
def test_sitemap_static_contains_expected_links(
|
||||
client: Client,
|
||||
settings: object,
|
||||
) -> None:
|
||||
"""Ensure the static sitemap contains the main site links across apps.
|
||||
|
||||
This test checks a representative set of URLs from core, twitch, kick, and
|
||||
youtube apps as well as some misc static files like /robots.txt.
|
||||
"""
|
||||
# Ensure deterministic BASE_URL
|
||||
settings.BASE_URL = "https://ttvdrops.lovinator.space"
|
||||
|
||||
response = client.get(reverse("sitemap-static"))
|
||||
assert response.status_code == 200
|
||||
assert response["Content-Type"] == "application/xml"
|
||||
|
||||
locs = _extract_locs(response.content)
|
||||
|
||||
base = settings.BASE_URL.rstrip("/")
|
||||
|
||||
expected_paths = [
|
||||
reverse("core:dashboard"),
|
||||
reverse("core:search"),
|
||||
reverse("core:debug"),
|
||||
reverse("core:dataset_backups"),
|
||||
reverse("core:docs_rss"),
|
||||
reverse("core:campaign_feed"),
|
||||
reverse("core:game_feed"),
|
||||
reverse("core:organization_feed"),
|
||||
reverse("core:reward_campaign_feed"),
|
||||
reverse("core:campaign_feed_atom"),
|
||||
reverse("core:campaign_feed_discord"),
|
||||
reverse("twitch:dashboard"),
|
||||
reverse("twitch:campaign_list"),
|
||||
reverse("twitch:games_grid"),
|
||||
reverse("twitch:games_list"),
|
||||
reverse("twitch:channel_list"),
|
||||
reverse("twitch:badge_list"),
|
||||
reverse("twitch:emote_gallery"),
|
||||
reverse("twitch:org_list"),
|
||||
reverse("twitch:reward_campaign_list"),
|
||||
reverse("twitch:export_campaigns_csv"),
|
||||
reverse("kick:dashboard"),
|
||||
reverse("kick:campaign_list"),
|
||||
reverse("kick:game_list"),
|
||||
reverse("kick:organization_list"),
|
||||
reverse("kick:campaign_feed"),
|
||||
reverse("kick:game_feed"),
|
||||
reverse("kick:organization_feed"),
|
||||
reverse("youtube:index"),
|
||||
"/about/",
|
||||
"/robots.txt",
|
||||
]
|
||||
|
||||
expected: set[str] = {base + p for p in expected_paths}
|
||||
|
||||
for url in expected:
|
||||
assert url in locs, f"Expected {url} in sitemap, found {len(locs)} entries"
|
||||
|
|
@ -256,14 +256,59 @@ def sitemap_static_view(request: HttpRequest) -> HttpResponse:
|
|||
HttpResponse: The rendered sitemap XML.
|
||||
"""
|
||||
# `request` is unused but required by Django's view signature.
|
||||
base_url: str = _build_base_url()
|
||||
base_url: str = _build_base_url().rstrip("/")
|
||||
sitemap_urls: list[dict[str, str]] = [
|
||||
{"loc": f"{base_url}/"},
|
||||
{"loc": f"{base_url}/twitch/"},
|
||||
{"loc": f"{base_url}/twitch/campaigns/"},
|
||||
{"loc": f"{base_url}/twitch/games/"},
|
||||
{"loc": f"{base_url}/kick/"},
|
||||
{"loc": f"{base_url}/youtube/"},
|
||||
{"loc": f"{base_url}{reverse('core:dashboard')}"},
|
||||
{"loc": f"{base_url}{reverse('core:search')}"},
|
||||
{"loc": f"{base_url}{reverse('core:debug')}"},
|
||||
{"loc": f"{base_url}{reverse('core:dataset_backups')}"},
|
||||
{"loc": f"{base_url}{reverse('core:docs_rss')}"},
|
||||
# Core RSS/Atom/Discord feeds
|
||||
{"loc": f"{base_url}{reverse('core:campaign_feed')}"},
|
||||
{"loc": f"{base_url}{reverse('core:game_feed')}"},
|
||||
{"loc": f"{base_url}{reverse('core:organization_feed')}"},
|
||||
{"loc": f"{base_url}{reverse('core:reward_campaign_feed')}"},
|
||||
{"loc": f"{base_url}{reverse('core:campaign_feed_atom')}"},
|
||||
{"loc": f"{base_url}{reverse('core:game_feed_atom')}"},
|
||||
{"loc": f"{base_url}{reverse('core:organization_feed_atom')}"},
|
||||
{"loc": f"{base_url}{reverse('core:reward_campaign_feed_atom')}"},
|
||||
{"loc": f"{base_url}{reverse('core:campaign_feed_discord')}"},
|
||||
{"loc": f"{base_url}{reverse('core:game_feed_discord')}"},
|
||||
{"loc": f"{base_url}{reverse('core:organization_feed_discord')}"},
|
||||
{"loc": f"{base_url}{reverse('core:reward_campaign_feed_discord')}"},
|
||||
# Twitch app pages
|
||||
{"loc": f"{base_url}{reverse('twitch:dashboard')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:campaign_list')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:games_grid')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:games_list')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:channel_list')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:badge_list')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:emote_gallery')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:org_list')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:reward_campaign_list')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:export_campaigns_csv')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:export_games_csv')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:export_organizations_csv')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:export_campaigns_json')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:export_games_json')}"},
|
||||
{"loc": f"{base_url}{reverse('twitch:export_organizations_json')}"},
|
||||
# Kick app pages and feeds
|
||||
{"loc": f"{base_url}{reverse('kick:dashboard')}"},
|
||||
{"loc": f"{base_url}{reverse('kick:campaign_list')}"},
|
||||
{"loc": f"{base_url}{reverse('kick:game_list')}"},
|
||||
{"loc": f"{base_url}{reverse('kick:organization_list')}"},
|
||||
{"loc": f"{base_url}{reverse('kick:campaign_feed')}"},
|
||||
{"loc": f"{base_url}{reverse('kick:game_feed')}"},
|
||||
{"loc": f"{base_url}{reverse('kick:organization_feed')}"},
|
||||
{"loc": f"{base_url}{reverse('kick:campaign_feed_atom')}"},
|
||||
{"loc": f"{base_url}{reverse('kick:game_feed_atom')}"},
|
||||
{"loc": f"{base_url}{reverse('kick:organization_feed_atom')}"},
|
||||
{"loc": f"{base_url}{reverse('kick:campaign_feed_discord')}"},
|
||||
{"loc": f"{base_url}{reverse('kick:game_feed_discord')}"},
|
||||
{"loc": f"{base_url}{reverse('kick:organization_feed_discord')}"},
|
||||
# YouTube
|
||||
{"loc": f"{base_url}{reverse('youtube:index')}"},
|
||||
# Misc/static
|
||||
{"loc": f"{base_url}/about/"},
|
||||
{"loc": f"{base_url}/robots.txt"},
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue