main
py 95 lines 4.7 KB
Raw
1 """Tests for the configurable external podcast link feature."""
2
3 from __future__ import annotations
4
5 import re
6 from pathlib import Path
7
8 REPO_ROOT = Path(__file__).resolve().parent.parent
9
10
11 def test_podcast_url_param_exists_in_hugo_config() -> None:
12 """hugo.toml must define the live Spotify podcast URL."""
13 config = (REPO_ROOT / "hugo.toml").read_text(encoding="utf-8")
14 assert "podcast_url" in config
15 assert 'podcast_url = "https://open.spotify.com/show/033xdn5nDMoCWxB3bss2dB"' in config
16
17
18 def test_footer_conditionally_renders_podcast_link() -> None:
19 """Footer template must conditionally render podcast link from site param."""
20 footer = (REPO_ROOT / "layouts" / "partials" / "footer.html").read_text(encoding="utf-8")
21 # Must trim before `with` so whitespace-only values are treated as falsy
22 assert "site.Params.podcast_url | strings.TrimSpace" in footer
23 # safeURL marks the value as trusted (bypasses scheme filtering) — safe here
24 # because the value comes from controlled site config, not user input.
25 assert "safeURL" in footer
26 # Verify the podcast link uses dot context with correct attrs
27 assert re.search(
28 r'<a\s+href="{{\s*\.\s*\|\s*safeURL\s*}}"[^>]*target="_blank"[^>]*rel="noopener noreferrer"[^>]*>Podcast</a>',
29 footer,
30 ), (
31 "Footer podcast link must use dot context piped through safeURL with target=_blank and rel=noopener noreferrer"
32 )
33
34
35 def test_report_shortcuts_link_weekly_reports_to_spotify() -> None:
36 """Weekly report shortcuts must expose the configured Spotify URL."""
37 shortcuts = (REPO_ROOT / "layouts" / "partials" / "report-shortcuts.html").read_text(
38 encoding="utf-8"
39 )
40 assert 'site.Params.podcast_url | default "" | strings.TrimSpace' in shortcuts
41 assert "if and $isWeekly $podcastURL" in shortcuts
42 assert re.search(
43 r'<a\s+href="{{\s*\$podcastURL\s*\|\s*safeURL\s*}}"[^>]*target="_blank"[^>]*rel="noopener noreferrer"[^>]*>Spotify</a>',
44 shortcuts,
45 ), "Weekly shortcuts must link to Spotify with target=_blank and rel=noopener noreferrer"
46
47
48 def test_header_exposes_spotify_button_when_podcast_url_is_configured() -> None:
49 """Header actions must expose the configured Spotify URL."""
50 header = (REPO_ROOT / "layouts" / "partials" / "header.html").read_text(encoding="utf-8")
51 assert 'site.Params.podcast_url | default "" | strings.TrimSpace' in header
52 assert 'class="icon-button spotify-button"' in header
53 assert re.search(
54 r'<a\s+class="icon-button spotify-button"\s+href="{{\s*\.\s*\|\s*safeURL\s*}}"[^>]*target="_blank"[^>]*rel="noopener noreferrer"[^>]*aria-label="Spotify"',
55 header,
56 ), (
57 "Header Spotify button must use configured URL with target=_blank and rel=noopener noreferrer"
58 )
59
60
61 def test_podcast_link_disabled_when_empty() -> None:
62 """Templates must guard against empty/whitespace podcast_url (disabled state)."""
63 footer = (REPO_ROOT / "layouts" / "partials" / "footer.html").read_text(encoding="utf-8")
64 header = (REPO_ROOT / "layouts" / "partials" / "header.html").read_text(encoding="utf-8")
65 shortcuts = (REPO_ROOT / "layouts" / "partials" / "report-shortcuts.html").read_text(
66 encoding="utf-8"
67 )
68 assert "{{- with site.Params.podcast_url | strings.TrimSpace }}" in footer, (
69 "Footer must render the podcast link only through a trimmed `with` guard"
70 )
71 assert (
72 '{{- $podcastURL := site.Params.podcast_url | default "" | strings.TrimSpace }}' in header
73 ), "Header must normalize podcast_url into $podcastURL before rendering"
74 assert "{{- with $podcastURL }}" in header, (
75 "Header must guard the Spotify button with `with $podcastURL`"
76 )
77 assert "{{- if and $isWeekly $podcastURL }}" in shortcuts, (
78 "Weekly shortcuts must require a non-empty $podcastURL before rendering Spotify"
79 )
80
81
82 def test_no_audio_hosting_or_player_pages() -> None:
83 """SquadScope must not host audio, embed players, or serve podcast RSS."""
84 layouts_dir = REPO_ROOT / "layouts"
85 # No podcast RSS template
86 for f in layouts_dir.rglob("*.xml"):
87 content = f.read_text(encoding="utf-8").lower()
88 assert "<enclosure" not in content, f"{f.name} must not contain podcast RSS enclosure tags"
89 assert "open.spotify.com/embed" not in content, f"{f.name} must not embed Spotify players"
90 # No audio player templates
91 for f in layouts_dir.rglob("*.html"):
92 content = f.read_text(encoding="utf-8").lower()
93 assert "<audio" not in content, f"{f.name} must not contain audio player elements"
94 assert "open.spotify.com/embed" not in content, f"{f.name} must not embed Spotify players"
95 assert "spotify:embed:" not in content, f"{f.name} must not contain Spotify embed URIs"