gabriel / musehub public
test_musehub_ui_new_repo_ssr.py python
122 lines 4.1 KB
d4eb1c39 Theme overhaul: domains, new-repo, MCP docs, copy icons; legacy CSS rem… Gabriel Cardona <cgcardona@gmail.com> 3d ago
1 """SSR tests for MuseHub repo creation endpoints (issue #562).
2
3 GET /new is now a redirect to /domains (domain-scoped creation flow).
4 The wizard form previously at /new no longer exists at that path.
5
6 Covers:
7 - test_new_repo_page_redirect_is_html_compatible — GET /new → 302 (no SSR form)
8 - test_new_repo_name_check_htmx_returns_available_html — HTMX → HTML span "Available"
9 - test_new_repo_name_check_htmx_returns_taken_html — HTMX → HTML span "taken"
10 - test_new_repo_name_check_json_path_unchanged — no HX-Request → JSON response
11 """
12 from __future__ import annotations
13
14 import pytest
15 from httpx import AsyncClient
16 from sqlalchemy.ext.asyncio import AsyncSession
17
18 from musehub.db.musehub_models import MusehubRepo
19
20
21 # ---------------------------------------------------------------------------
22 # Seed helper
23 # ---------------------------------------------------------------------------
24
25
26 async def _seed_repo(
27 db: AsyncSession,
28 owner: str = "existingowner",
29 slug: str = "taken-repo",
30 ) -> None:
31 """Seed a public repo so the slug appears as taken in check requests."""
32 repo = MusehubRepo(
33 name=slug,
34 owner=owner,
35 slug=slug,
36 visibility="public",
37 owner_user_id="seed-uid",
38 )
39 db.add(repo)
40 await db.commit()
41
42
43 # ---------------------------------------------------------------------------
44 # Tests — /new redirect (form moved to /domains/@author/slug/new)
45 # ---------------------------------------------------------------------------
46
47
48 @pytest.mark.anyio
49 async def test_new_repo_page_redirect_is_html_compatible(
50 client: AsyncClient,
51 db_session: AsyncSession,
52 ) -> None:
53 """GET /new returns a 302 redirect — no SSR wizard form at this path.
54
55 Repository creation is now domain-scoped; the wizard moved to
56 /domains/@{author}/{slug}/new. This test confirms the old path
57 cleanly redirects without requiring authentication.
58 """
59 response = await client.get("/new", follow_redirects=False)
60 assert response.status_code == 302
61 assert "/domains" in response.headers["location"]
62
63
64 # ---------------------------------------------------------------------------
65 # Tests — /new/check availability endpoint
66 # ---------------------------------------------------------------------------
67
68
69 @pytest.mark.anyio
70 async def test_new_repo_name_check_htmx_returns_available_html(
71 client: AsyncClient,
72 db_session: AsyncSession,
73 ) -> None:
74 """GET /new/check with HX-Request header returns an HTML availability span.
75
76 The span is swapped into #name-check by HTMX — no JS needed.
77 """
78 response = await client.get(
79 "/new/check",
80 params={"owner": "newowner", "slug": "unique-name-xyz-123"},
81 headers={"HX-Request": "true"},
82 )
83 assert response.status_code == 200
84 assert "text/html" in response.headers["content-type"]
85 assert "<span" in response.text
86 assert "Available" in response.text
87
88
89 @pytest.mark.anyio
90 async def test_new_repo_name_check_htmx_returns_taken_html(
91 client: AsyncClient,
92 db_session: AsyncSession,
93 ) -> None:
94 """GET /new/check for an existing slug returns a "taken" HTML span."""
95 await _seed_repo(db_session, owner="existingowner", slug="taken-repo")
96 response = await client.get(
97 "/new/check",
98 params={"owner": "existingowner", "slug": "taken-repo"},
99 headers={"HX-Request": "true"},
100 )
101 assert response.status_code == 200
102 assert "text/html" in response.headers["content-type"]
103 body = response.text
104 assert "<span" in body
105 assert "taken" in body.lower() or "✗" in body
106
107
108 @pytest.mark.anyio
109 async def test_new_repo_name_check_json_path_unchanged(
110 client: AsyncClient,
111 db_session: AsyncSession,
112 ) -> None:
113 """GET /new/check without HX-Request header returns JSON — backward-compat path."""
114 response = await client.get(
115 "/new/check",
116 params={"owner": "anyowner", "slug": "any-slug-999"},
117 )
118 assert response.status_code == 200
119 assert response.headers["content-type"].startswith("application/json")
120 data = response.json()
121 assert "available" in data
122 assert isinstance(data["available"], bool)