gabriel / musehub public
test_musehub_ui_explore_ssr.py python
127 lines 4.1 KB
Raw
sha256:a10adeeb7a0169cb9900f9806ed7a973047258abb6283724fe55e8eb68ff3f0a init: musehub initial commit Human 171 days ago
1 """SSR tests for MuseHub explore page — issue #576.
2
3 Validates that repo data is rendered server-side into HTML (not deferred to
4 client JS) and that HTMX fragment requests return bare grid HTML without the
5 full page shell.
6
7 Covers GET /explore:
8 - test_explore_page_renders_repo_name_server_side — repo name in HTML
9 - test_explore_page_sort_filter_form_has_hx_get — filter form has hx-get
10 - test_explore_page_genre_filter_narrows_repos — ?topic=jazz → jazz-tagged
11 - test_explore_page_htmx_fragment_path — HX-Request → fragment only
12 - test_explore_page_empty_state_when_no_repos — no public repos → empty state
13 """
14 from __future__ import annotations
15
16 import pytest
17 from httpx import AsyncClient
18 from sqlalchemy.ext.asyncio import AsyncSession
19
20 from musehub.db.musehub_models import MusehubRepo
21
22
23 # ---------------------------------------------------------------------------
24 # Seed helpers
25 # ---------------------------------------------------------------------------
26
27
28 async def _make_public_repo(
29 db: AsyncSession,
30 *,
31 owner: str = "artist",
32 slug: str = "cool-album",
33 name: str = "cool-album",
34 tags: list[str] | None = None,
35 star_count: int = 0,
36 ) -> MusehubRepo:
37 """Seed a public repo and return the ORM object."""
38 repo = MusehubRepo(
39 name=name,
40 owner=owner,
41 slug=slug,
42 visibility="public",
43 owner_user_id=f"uid-{slug}",
44 tags=tags or [],
45 )
46 db.add(repo)
47 await db.commit()
48 await db.refresh(repo)
49 return repo
50
51
52 # ---------------------------------------------------------------------------
53 # Explore page SSR tests
54 # ---------------------------------------------------------------------------
55
56
57 @pytest.mark.anyio
58 async def test_explore_page_renders_repo_name_server_side(
59 client: AsyncClient,
60 db_session: AsyncSession,
61 ) -> None:
62 """Repo name is in the HTML response without any client-side JS execution."""
63 await _make_public_repo(db_session, slug="jazz-sessions", name="jazz-sessions")
64 response = await client.get("/explore")
65 assert response.status_code == 200
66 assert "text/html" in response.headers["content-type"]
67 assert "jazz-sessions" in response.text
68
69
70 @pytest.mark.anyio
71 async def test_explore_page_sort_filter_form_has_hx_get(
72 client: AsyncClient,
73 db_session: AsyncSession,
74 ) -> None:
75 """Filter form has hx-get attribute enabling HTMX partial swap."""
76 response = await client.get("/explore")
77 assert response.status_code == 200
78 assert 'hx-get="/explore"' in response.text
79
80
81 @pytest.mark.anyio
82 async def test_explore_page_genre_filter_narrows_repos(
83 client: AsyncClient,
84 db_session: AsyncSession,
85 ) -> None:
86 """?topic=jazz returns only jazz-tagged repos (genre filter works SSR)."""
87 await _make_public_repo(
88 db_session, slug="jazz-album", name="jazz-album", tags=["jazz", "piano"]
89 )
90 await _make_public_repo(
91 db_session, slug="rock-album", name="rock-album", tags=["rock", "guitar"]
92 )
93 response = await client.get("/explore?topic=jazz")
94 assert response.status_code == 200
95 body = response.text
96 assert "jazz-album" in body
97 assert "rock-album" not in body
98
99
100 @pytest.mark.anyio
101 async def test_explore_page_htmx_fragment_path(
102 client: AsyncClient,
103 db_session: AsyncSession,
104 ) -> None:
105 """HX-Request: true returns a bare HTML fragment without the full page shell."""
106 await _make_public_repo(db_session, slug="htmx-repo", name="htmx-repo")
107 response = await client.get(
108 "/explore",
109 headers={"HX-Request": "true"},
110 )
111 assert response.status_code == 200
112 assert "<html" not in response.text
113 assert "<head" not in response.text
114 # Fragment should contain the repo or empty-state markup.
115 assert "htmx-repo" in response.text or "No repositories found" in response.text
116
117
118 @pytest.mark.anyio
119 async def test_explore_page_empty_state_when_no_repos(
120 client: AsyncClient,
121 db_session: AsyncSession,
122 ) -> None:
123 """When no public repos exist the empty-state message is rendered SSR."""
124 response = await client.get("/explore")
125 assert response.status_code == 200
126 assert "No repositories found" in response.text
127
File History 1 commit
sha256:a10adeeb7a0169cb9900f9806ed7a973047258abb6283724fe55e8eb68ff3f0a init: musehub initial commit Human 171 days ago