gabriel / musehub public
test_musehub_ui_releases_ssr.py python
171 lines 5.8 KB
Raw
sha256:9590cee1e0ccd6c76528f005b95d634d80f5019f0dcb7c371e149adc31d1fb65 refactor: enforce gRPC framing on all MWP wire traffic Sonnet 4.6 minor ⚠ breaking 156 days ago
1 """SSR tests for MuseHub releases UI pages — issue #572.
2
3 Validates that release data is rendered server-side into HTML (not deferred
4 to client JS) and that HTMX fragment requests return bare HTML without the
5 full page shell.
6
7 Covers GET /{owner}/{repo_slug}/releases:
8 - test_releases_list_renders_tag_server_side — release tag in HTML
9 - test_releases_list_shows_prerelease_badge — pre-release badge in HTML
10 - test_releases_list_htmx_fragment_path — HX-Request: true → bare fragment
11 - test_releases_list_empty_state_when_no_releases — no releases → empty state
12
13 Covers GET /{owner}/{repo_slug}/releases/{tag}:
14 - test_release_detail_renders_tag_server_side — tag in HTML
15 - test_release_detail_shows_audio_player_container — audioUrl → #release-audio-player div
16 - test_release_detail_unknown_tag_404 — unknown tag → 404
17 """
18 from __future__ import annotations
19
20 import pytest
21 from httpx import AsyncClient
22 from sqlalchemy.ext.asyncio import AsyncSession
23
24 from musehub.db.musehub_models import (
25 MusehubRelease,
26 MusehubRepo,
27 )
28
29
30 # ---------------------------------------------------------------------------
31 # Seed helpers
32 # ---------------------------------------------------------------------------
33
34
35 async def _make_repo(db: AsyncSession, owner: str = "musician", slug: str = "ssr-album") -> str:
36 """Seed a public repo and return its repo_id string."""
37 repo = MusehubRepo(
38 name=slug,
39 owner=owner,
40 slug=slug,
41 visibility="public",
42 owner_user_id="uid-ssr-musician",
43 )
44 db.add(repo)
45 await db.commit()
46 await db.refresh(repo)
47 return str(repo.repo_id)
48
49
50 async def _make_release(
51 db: AsyncSession,
52 repo_id: str,
53 *,
54 tag: str = "v1.0",
55 title: str = "Version 1.0",
56 body: str = "Release notes here.",
57 author: str = "musician",
58 channel: str = "stable",
59 is_draft: bool = False,
60 mp3_url: str | None = None,
61 ) -> MusehubRelease:
62 """Seed a release and return the ORM object."""
63 download_urls = {}
64 if mp3_url:
65 download_urls["mp3"] = mp3_url
66 release = MusehubRelease(
67 repo_id=repo_id,
68 tag=tag,
69 title=title,
70 body=body,
71 author=author,
72 channel=channel,
73 is_draft=is_draft,
74 download_urls=download_urls,
75 )
76 db.add(release)
77 await db.commit()
78 await db.refresh(release)
79 return release
80
81
82 # ---------------------------------------------------------------------------
83 # Releases list SSR tests
84 # ---------------------------------------------------------------------------
85
86
87 async def test_releases_list_renders_tag_server_side(
88 client: AsyncClient,
89 db_session: AsyncSession,
90 ) -> None:
91 """Release tag is in the HTML response server-side (no JS required)."""
92 repo_id = await _make_repo(db_session)
93 await _make_release(db_session, repo_id, tag="v2.5.0", title="Groove update 2.5")
94 response = await client.get("/musician/ssr-album/releases")
95 assert response.status_code == 200
96 assert "text/html" in response.headers["content-type"]
97 assert "v2.5.0" in response.text
98
99
100 async def test_releases_list_shows_prerelease_badge(
101 client: AsyncClient,
102 db_session: AsyncSession,
103 ) -> None:
104 """Pre-release badge renders server-side for releases flagged as pre-release."""
105 repo_id = await _make_repo(db_session)
106 await _make_release(db_session, repo_id, tag="v1.0-beta", channel="beta")
107 response = await client.get("/musician/ssr-album/releases")
108 assert response.status_code == 200
109 assert "Pre-release" in response.text
110 assert "v1.0-beta" in response.text
111
112
113 async def test_releases_list_htmx_fragment_path(
114 client: AsyncClient,
115 db_session: AsyncSession,
116 ) -> None:
117 """HX-Request: true returns a bare HTML fragment without the full page shell."""
118 repo_id = await _make_repo(db_session)
119 await _make_release(db_session, repo_id, tag="v2.0", title="Earlier release")
120 await _make_release(db_session, repo_id, tag="v3.0", title="Major release")
121 response = await client.get(
122 "/musician/ssr-album/releases",
123 headers={"HX-Request": "true"},
124 )
125 assert response.status_code == 200
126 assert "<html" not in response.text
127 assert "<head" not in response.text
128 assert "v2.0" in response.text
129
130
131 async def test_releases_list_empty_state_when_no_releases(
132 client: AsyncClient,
133 db_session: AsyncSession,
134 ) -> None:
135 """Empty release list renders the empty state message server-side."""
136 await _make_repo(db_session)
137 response = await client.get("/musician/ssr-album/releases")
138 assert response.status_code == 200
139 # empty_state macro renders "No releases yet" when the list is empty.
140 assert "No releases yet" in response.text
141
142
143 # ---------------------------------------------------------------------------
144 # Release detail SSR tests
145 # ---------------------------------------------------------------------------
146
147
148 async def test_release_detail_renders_tag_server_side(
149 client: AsyncClient,
150 db_session: AsyncSession,
151 ) -> None:
152 """Release tag appears in the detail page HTML server-side."""
153 repo_id = await _make_repo(db_session)
154 await _make_release(db_session, repo_id, tag="v1.2.3", title="Polished mix")
155 response = await client.get("/musician/ssr-album/releases/v1.2.3")
156 assert response.status_code == 200
157 assert "text/html" in response.headers["content-type"]
158 assert "v1.2.3" in response.text
159 # Title should appear too.
160 assert "Polished mix" in response.text
161
162
163
164 async def test_release_detail_unknown_tag_404(
165 client: AsyncClient,
166 db_session: AsyncSession,
167 ) -> None:
168 """Non-existent release tag returns 404."""
169 await _make_repo(db_session)
170 response = await client.get("/musician/ssr-album/releases/vNOPE")
171 assert response.status_code == 404
File History 1 commit
sha256:9590cee1e0ccd6c76528f005b95d634d80f5019f0dcb7c371e149adc31d1fb65 refactor: enforce gRPC framing on all MWP wire traffic Sonnet 4.6 minor ⚠ 156 days ago