gabriel / musehub public

test_musehub_ui_new_repo_ssr.py file-level

at sha256:3 · View file ↗ · Intel ↗

History
1 files
1 commits
0 hotspots
0 🧊 dead
0 πŸ’₯ blast risk
sha256:0 fix: fall back to any indexed mpack in read_object_bytes when push mpac… · gabriel · Jun 17, 2026
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 datetime import datetime, timezone
19
20 from musehub.core.genesis import compute_identity_id, compute_repo_id
21 from musehub.db.musehub_repo_models import MusehubRepo
22
23
24 # ---------------------------------------------------------------------------
25 # Seed helper
26 # ---------------------------------------------------------------------------
27
28
29 async def _seed_repo(
30 db: AsyncSession,
31 owner: str = "existingowner",
32 slug: str = "taken-repo",
33 ) -> None:
34 """Seed a public repo so the slug appears as taken in check requests."""
35 owner_id = compute_identity_id(owner.encode())
36 created_at = datetime.now(tz=timezone.utc)
37 repo = MusehubRepo(
38 repo_id=compute_repo_id(owner_id, slug, "code", created_at.isoformat()),
39 name=slug,
40 owner=owner,
41 slug=slug,
42 visibility="public",
43 owner_user_id=owner_id,
44 created_at=created_at,
45 updated_at=created_at,
46 )
47 db.add(repo)
48 await db.commit()
49
50
51 # ---------------------------------------------------------------------------
52 # Tests β€” /new redirect (form moved to /domains/@author/slug/new)
53 # ---------------------------------------------------------------------------
54
55
56 async def test_new_repo_page_redirect_is_html_compatible(
57 client: AsyncClient,
58 db_session: AsyncSession,
59 ) -> None:
60 """GET /new returns a 302 redirect β€” no SSR wizard form at this path.
61
62 Repository creation is now domain-scoped; the wizard moved to
63 /domains/@{author}/{slug}/new. This test confirms the old path
64 cleanly redirects without requiring authentication.
65 """
66 response = await client.get("/new", follow_redirects=False)
67 assert response.status_code == 302
68 assert "/domains" in response.headers["location"]
69
70
71 # ---------------------------------------------------------------------------
72 # Tests β€” /new/check availability endpoint
73 # ---------------------------------------------------------------------------
74
75
76 async def test_new_repo_name_check_htmx_returns_available_html(
77 client: AsyncClient,
78 db_session: AsyncSession,
79 ) -> None:
80 """GET /new/check with HX-Request header returns an HTML availability span.
81
82 The span is swapped into #name-check by HTMX β€” no JS needed.
83 """
84 response = await client.get(
85 "/new/check",
86 params={"owner": "newowner", "slug": "unique-name-xyz-123"},
87 headers={"HX-Request": "true"},
88 )
89 assert response.status_code == 200
90 assert "text/html" in response.headers["content-type"]
91 assert "<span" in response.text
92 assert "Available" in response.text
93
94
95 async def test_new_repo_name_check_htmx_returns_taken_html(
96 client: AsyncClient,
97 db_session: AsyncSession,
98 ) -> None:
99 """GET /new/check for an existing slug returns a "taken" HTML span."""
100 await _seed_repo(db_session, owner="existingowner", slug="taken-repo")
101 response = await client.get(
102 "/new/check",
103 params={"owner": "existingowner", "slug": "taken-repo"},
104 headers={"HX-Request": "true"},
105 )
106 assert response.status_code == 200
107 assert "text/html" in response.headers["content-type"]
108 body = response.text
109 assert "<span" in body
110 assert "taken" in body.lower() or "βœ—" in body
111
112
113 async def test_new_repo_name_check_json_path_unchanged(
114 client: AsyncClient,
115 db_session: AsyncSession,
116 ) -> None:
117 """GET /new/check without HX-Request header returns JSON β€” backward-compat path."""
118 response = await client.get(
119 "/new/check",
120 params={"owner": "anyowner", "slug": "any-slug-999"},
121 )
122 assert response.status_code == 200
123 assert response.headers["content-type"].startswith("application/json")
124 data = response.json()
125 assert "available" in data
126 assert isinstance(data["available"], bool)