gabriel / musehub public
test_generic_domain.py python
167 lines 5.4 KB
Raw
sha256:7d6dd8f4a89e2d1fef2d84f6e65feaff51385d382f466766b7f690a22ec18e32 fix: fall back to DB ancestry check when mpack-only fast-fo… Sonnet 4.6 patch 5 days ago
1 """TDD tests for the 'generic' domain as a first-class explicit value.
2
3 Design decision: repos without a recognised domain plugin must resolve to
4 'generic' — a named, intentional domain — rather than an empty string or None.
5
6 This covers four surfaces:
7 1. GENERIC_DOMAIN constant exported from musehub.services.musehub_repository
8 2. RepoResponse.domain field resolves to 'generic' when domain_id is None
9 3. _build_repos_out — domain key is 'generic', never '' or None
10 4. profile.html chip — 'generic' renders a distinct icon (not gray #94a3b8)
11 5. POST /api/repos API — omitting or empty domain returns domain='generic'
12
13 Tests are RED-first. Each assertion drives one concrete implementation decision.
14 """
15 from __future__ import annotations
16
17 import pytest
18 from httpx import AsyncClient, ASGITransport
19 from sqlalchemy.ext.asyncio import AsyncSession
20
21 from muse.core.types import long_id
22 from musehub.main import app
23
24
25 # ---------------------------------------------------------------------------
26 # Helpers
27 # ---------------------------------------------------------------------------
28
29 _OWNER = "testuser"
30
31
32 # ---------------------------------------------------------------------------
33 # 1. GENERIC_DOMAIN constant
34 # ---------------------------------------------------------------------------
35
36
37 def test_generic_domain_constant_exported() -> None:
38 from musehub.services.musehub_repository import GENERIC_DOMAIN
39 assert GENERIC_DOMAIN == "generic"
40
41
42 # ---------------------------------------------------------------------------
43 # 2. RepoResponse.domain field is present and defaults to 'generic'
44 # ---------------------------------------------------------------------------
45
46
47 def test_repo_response_has_domain_field() -> None:
48 from musehub.models.musehub import RepoResponse
49 from datetime import datetime, timezone
50
51 now = datetime.now(timezone.utc)
52 resp = RepoResponse(
53 repo_id=long_id("a" * 64),
54 name="test",
55 owner="testuser",
56 slug="test",
57 visibility="public",
58 owner_user_id=long_id("b" * 64),
59 clone_url="https://localhost:1337/api/repos/test",
60 description="",
61 tags=[],
62 domain_id=None,
63 default_branch="main",
64 created_at=now,
65 updated_at=now,
66 pushed_at=None,
67 )
68 assert resp.domain == "generic"
69
70
71 def test_repo_response_domain_set_explicitly() -> None:
72 from musehub.models.musehub import RepoResponse
73 from datetime import datetime, timezone
74
75 now = datetime.now(timezone.utc)
76 resp = RepoResponse(
77 repo_id=long_id("a" * 64),
78 name="test",
79 owner="testuser",
80 slug="test",
81 visibility="public",
82 owner_user_id=long_id("b" * 64),
83 clone_url="https://localhost:1337/api/repos/test",
84 description="",
85 tags=[],
86 domain_id=None,
87 domain="code",
88 default_branch="main",
89 created_at=now,
90 updated_at=now,
91 pushed_at=None,
92 )
93 assert resp.domain == "code"
94
95
96 # ---------------------------------------------------------------------------
97 # 3. create_repo service — returns domain='generic' when no domain specified
98 # ---------------------------------------------------------------------------
99
100
101 @pytest.mark.asyncio
102 async def test_create_repo_no_domain_returns_generic(db_session: AsyncSession) -> None:
103 from musehub.services.musehub_repository import create_repo, GENERIC_DOMAIN
104
105 resp = await create_repo(
106 db_session,
107 name="no-domain-repo",
108 owner=_OWNER,
109 visibility="public",
110 owner_user_id=long_id("a" * 64),
111 owner_identity_id=long_id("a" * 64),
112 )
113 await db_session.commit()
114
115 assert resp.domain == GENERIC_DOMAIN
116
117
118 @pytest.mark.asyncio
119 async def test_create_repo_empty_domain_returns_generic(db_session: AsyncSession) -> None:
120 from musehub.services.musehub_repository import create_repo, GENERIC_DOMAIN
121
122 resp = await create_repo(
123 db_session,
124 name="empty-domain-repo",
125 owner=_OWNER,
126 visibility="public",
127 owner_user_id=long_id("a" * 64),
128 owner_identity_id=long_id("a" * 64),
129 domain="",
130 )
131 await db_session.commit()
132
133 assert resp.domain == GENERIC_DOMAIN
134
135
136 # ---------------------------------------------------------------------------
137 # 4. _build_repos_out — domain key is never '' or None
138 # ---------------------------------------------------------------------------
139
140
141
142
143 # ---------------------------------------------------------------------------
144 # 6. API — POST /api/repos without domain returns domain='generic'
145 # ---------------------------------------------------------------------------
146
147
148 @pytest.mark.asyncio
149 async def test_create_repo_api_omitting_domain_returns_generic(
150 client: AsyncClient,
151 auth_headers: dict[str, str],
152 ) -> None:
153 payload = {"name": "no-domain-api-repo", "owner": "testuser", "visibility": "public"}
154 resp = await client.post("/api/repos", json=payload, headers=auth_headers)
155 assert resp.status_code == 201, resp.text
156 assert resp.json()["domain"] == "generic"
157
158
159 @pytest.mark.asyncio
160 async def test_create_repo_api_empty_domain_returns_generic(
161 client: AsyncClient,
162 auth_headers: dict[str, str],
163 ) -> None:
164 payload = {"name": "empty-domain-api-repo", "owner": "testuser", "visibility": "public", "domain": ""}
165 resp = await client.post("/api/repos", json=payload, headers=auth_headers)
166 assert resp.status_code == 201, resp.text
167 assert resp.json()["domain"] == "generic"
File History 1 commit
sha256:7d6dd8f4a89e2d1fef2d84f6e65feaff51385d382f466766b7f690a22ec18e32 fix: fall back to DB ancestry check when mpack-only fast-fo… Sonnet 4.6 patch 5 days ago