gabriel / musehub public
test_generic_domain.py python
166 lines 5.4 KB
Raw
sha256:bb2baaabdd19320bde50cb69d447fd1c1e571467df729be1a23b5e93064b046a feat(intel): standardize headers, gauge icon, velocity card… Sonnet 4.6 minor ⚠ breaking 143 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 musehub.main import app
22
23
24 # ---------------------------------------------------------------------------
25 # Helpers
26 # ---------------------------------------------------------------------------
27
28 _OWNER = "testuser"
29
30
31 # ---------------------------------------------------------------------------
32 # 1. GENERIC_DOMAIN constant
33 # ---------------------------------------------------------------------------
34
35
36 def test_generic_domain_constant_exported() -> None:
37 from musehub.services.musehub_repository import GENERIC_DOMAIN
38 assert GENERIC_DOMAIN == "generic"
39
40
41 # ---------------------------------------------------------------------------
42 # 2. RepoResponse.domain field is present and defaults to 'generic'
43 # ---------------------------------------------------------------------------
44
45
46 def test_repo_response_has_domain_field() -> None:
47 from musehub.models.musehub import RepoResponse
48 from datetime import datetime, timezone
49
50 now = datetime.now(timezone.utc)
51 resp = RepoResponse(
52 repo_id="sha256:" + "a" * 64,
53 name="test",
54 owner="testuser",
55 slug="test",
56 visibility="public",
57 owner_user_id="sha256:" + "b" * 64,
58 clone_url="https://localhost:1337/api/repos/test",
59 description="",
60 tags=[],
61 domain_id=None,
62 default_branch="main",
63 created_at=now,
64 updated_at=now,
65 pushed_at=None,
66 )
67 assert resp.domain == "generic"
68
69
70 def test_repo_response_domain_set_explicitly() -> None:
71 from musehub.models.musehub import RepoResponse
72 from datetime import datetime, timezone
73
74 now = datetime.now(timezone.utc)
75 resp = RepoResponse(
76 repo_id="sha256:" + "a" * 64,
77 name="test",
78 owner="testuser",
79 slug="test",
80 visibility="public",
81 owner_user_id="sha256:" + "b" * 64,
82 clone_url="https://localhost:1337/api/repos/test",
83 description="",
84 tags=[],
85 domain_id=None,
86 domain="code",
87 default_branch="main",
88 created_at=now,
89 updated_at=now,
90 pushed_at=None,
91 )
92 assert resp.domain == "code"
93
94
95 # ---------------------------------------------------------------------------
96 # 3. create_repo service — returns domain='generic' when no domain specified
97 # ---------------------------------------------------------------------------
98
99
100 @pytest.mark.asyncio
101 async def test_create_repo_no_domain_returns_generic(db_session: AsyncSession) -> None:
102 from musehub.services.musehub_repository import create_repo, GENERIC_DOMAIN
103
104 resp = await create_repo(
105 db_session,
106 name="no-domain-repo",
107 owner=_OWNER,
108 visibility="public",
109 owner_user_id="sha256:" + "a" * 64,
110 owner_identity_id="sha256:" + "a" * 64,
111 )
112 await db_session.commit()
113
114 assert resp.domain == GENERIC_DOMAIN
115
116
117 @pytest.mark.asyncio
118 async def test_create_repo_empty_domain_returns_generic(db_session: AsyncSession) -> None:
119 from musehub.services.musehub_repository import create_repo, GENERIC_DOMAIN
120
121 resp = await create_repo(
122 db_session,
123 name="empty-domain-repo",
124 owner=_OWNER,
125 visibility="public",
126 owner_user_id="sha256:" + "a" * 64,
127 owner_identity_id="sha256:" + "a" * 64,
128 domain="",
129 )
130 await db_session.commit()
131
132 assert resp.domain == GENERIC_DOMAIN
133
134
135 # ---------------------------------------------------------------------------
136 # 4. _build_repos_out — domain key is never '' or None
137 # ---------------------------------------------------------------------------
138
139
140
141
142 # ---------------------------------------------------------------------------
143 # 6. API — POST /api/repos without domain returns domain='generic'
144 # ---------------------------------------------------------------------------
145
146
147 @pytest.mark.asyncio
148 async def test_create_repo_api_omitting_domain_returns_generic(
149 client: AsyncClient,
150 auth_headers: dict[str, str],
151 ) -> None:
152 payload = {"name": "no-domain-api-repo", "owner": "testuser", "visibility": "public"}
153 resp = await client.post("/api/repos", json=payload, headers=auth_headers)
154 assert resp.status_code == 201, resp.text
155 assert resp.json()["domain"] == "generic"
156
157
158 @pytest.mark.asyncio
159 async def test_create_repo_api_empty_domain_returns_generic(
160 client: AsyncClient,
161 auth_headers: dict[str, str],
162 ) -> None:
163 payload = {"name": "empty-domain-api-repo", "owner": "testuser", "visibility": "public", "domain": ""}
164 resp = await client.post("/api/repos", json=payload, headers=auth_headers)
165 assert resp.status_code == 201, resp.text
166 assert resp.json()["domain"] == "generic"
File History 1 commit
sha256:bb2baaabdd19320bde50cb69d447fd1c1e571467df729be1a23b5e93064b046a feat(intel): standardize headers, gauge icon, velocity card… Sonnet 4.6 minor 143 days ago