gabriel / musehub public
test_musehub_ui_new_repo_ssr.py python
118 lines 4.0 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 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 async def test_new_repo_page_redirect_is_html_compatible(
49 client: AsyncClient,
50 db_session: AsyncSession,
51 ) -> None:
52 """GET /new returns a 302 redirect — no SSR wizard form at this path.
53
54 Repository creation is now domain-scoped; the wizard moved to
55 /domains/@{author}/{slug}/new. This test confirms the old path
56 cleanly redirects without requiring authentication.
57 """
58 response = await client.get("/new", follow_redirects=False)
59 assert response.status_code == 302
60 assert "/domains" in response.headers["location"]
61
62
63 # ---------------------------------------------------------------------------
64 # Tests — /new/check availability endpoint
65 # ---------------------------------------------------------------------------
66
67
68 async def test_new_repo_name_check_htmx_returns_available_html(
69 client: AsyncClient,
70 db_session: AsyncSession,
71 ) -> None:
72 """GET /new/check with HX-Request header returns an HTML availability span.
73
74 The span is swapped into #name-check by HTMX — no JS needed.
75 """
76 response = await client.get(
77 "/new/check",
78 params={"owner": "newowner", "slug": "unique-name-xyz-123"},
79 headers={"HX-Request": "true"},
80 )
81 assert response.status_code == 200
82 assert "text/html" in response.headers["content-type"]
83 assert "<span" in response.text
84 assert "Available" in response.text
85
86
87 async def test_new_repo_name_check_htmx_returns_taken_html(
88 client: AsyncClient,
89 db_session: AsyncSession,
90 ) -> None:
91 """GET /new/check for an existing slug returns a "taken" HTML span."""
92 await _seed_repo(db_session, owner="existingowner", slug="taken-repo")
93 response = await client.get(
94 "/new/check",
95 params={"owner": "existingowner", "slug": "taken-repo"},
96 headers={"HX-Request": "true"},
97 )
98 assert response.status_code == 200
99 assert "text/html" in response.headers["content-type"]
100 body = response.text
101 assert "<span" in body
102 assert "taken" in body.lower() or "✗" in body
103
104
105 async def test_new_repo_name_check_json_path_unchanged(
106 client: AsyncClient,
107 db_session: AsyncSession,
108 ) -> None:
109 """GET /new/check without HX-Request header returns JSON — backward-compat path."""
110 response = await client.get(
111 "/new/check",
112 params={"owner": "anyowner", "slug": "any-slug-999"},
113 )
114 assert response.status_code == 200
115 assert response.headers["content-type"].startswith("application/json")
116 data = response.json()
117 assert "available" in data
118 assert isinstance(data["available"], bool)
File History 1 commit
sha256:9590cee1e0ccd6c76528f005b95d634d80f5019f0dcb7c371e149adc31d1fb65 refactor: enforce gRPC framing on all MWP wire traffic Sonnet 4.6 minor ⚠ 156 days ago