gabriel / musehub public
test_musehub_profile_service.py python
173 lines 6.6 KB
7923a405 test(supercharge): comprehensive test suite overhaul — all 11 points Gabriel Cardona <gabriel@tellurstori.com> 6d ago
1 """Unit tests for musehub/services/musehub_profile.py.
2
3 Tests the service-layer profile functions directly (no HTTP), covering:
4 - Profile CRUD (create, get_by_username, get_by_user_id, update)
5 - Contribution graph shape and zero-commit baseline
6 - get_public_repos filters private repos
7 - get_session_credits baseline (no sessions → 0)
8 """
9 from __future__ import annotations
10
11 import pytest
12 from sqlalchemy.ext.asyncio import AsyncSession
13
14 from musehub.models.musehub import ProfileUpdateRequest
15 from musehub.services import musehub_profile
16 from tests.factories import create_profile, create_repo
17
18
19 # ---------------------------------------------------------------------------
20 # create_profile / get_profile_by_username
21 # ---------------------------------------------------------------------------
22
23 @pytest.mark.anyio
24 async def test_create_profile_and_get_by_username(db_session: AsyncSession) -> None:
25 profile = await create_profile(db_session, username="artistone", display_name="Artist One")
26 found = await musehub_profile.get_profile_by_username(db_session, "artistone")
27 assert found is not None
28 assert found.username == "artistone"
29 assert found.display_name == "Artist One"
30
31
32 @pytest.mark.anyio
33 async def test_get_profile_by_username_missing_returns_none(db_session: AsyncSession) -> None:
34 result = await musehub_profile.get_profile_by_username(db_session, "ghost-user")
35 assert result is None
36
37
38 @pytest.mark.anyio
39 async def test_get_profile_by_user_id(db_session: AsyncSession) -> None:
40 profile = await create_profile(db_session, username="byid-user")
41 found = await musehub_profile.get_profile_by_user_id(db_session, profile.user_id)
42 assert found is not None
43 assert found.username == "byid-user"
44
45
46 @pytest.mark.anyio
47 async def test_get_profile_by_user_id_missing_returns_none(db_session: AsyncSession) -> None:
48 result = await musehub_profile.get_profile_by_user_id(db_session, "00000000-dead-beef-0000-000000000000")
49 assert result is None
50
51
52 # ---------------------------------------------------------------------------
53 # update_profile
54 # ---------------------------------------------------------------------------
55
56 @pytest.mark.anyio
57 async def test_update_profile_bio(db_session: AsyncSession) -> None:
58 orm_profile = await create_profile(db_session, username="bio-user", bio="old bio")
59 await musehub_profile.update_profile(
60 db_session,
61 orm_profile,
62 ProfileUpdateRequest(bio="new bio"),
63 )
64 updated = await musehub_profile.get_profile_by_username(db_session, "bio-user")
65 assert updated is not None
66 assert updated.bio == "new bio"
67
68
69 @pytest.mark.anyio
70 async def test_update_profile_display_name(db_session: AsyncSession) -> None:
71 orm_profile = await create_profile(db_session, username="name-user", display_name="Old Name")
72 await musehub_profile.update_profile(
73 db_session,
74 orm_profile,
75 ProfileUpdateRequest(display_name="New Name"),
76 )
77 updated = await musehub_profile.get_profile_by_username(db_session, "name-user")
78 assert updated is not None
79 assert updated.display_name == "New Name"
80
81
82 # ---------------------------------------------------------------------------
83 # get_public_repos
84 # ---------------------------------------------------------------------------
85
86 @pytest.mark.anyio
87 async def test_get_public_repos_returns_public_only(db_session: AsyncSession) -> None:
88 profile = await create_profile(db_session, username="pub-repo-user")
89 await create_repo(
90 db_session,
91 owner="pub-repo-user",
92 owner_user_id=profile.user_id,
93 slug="public-one",
94 visibility="public",
95 )
96 await create_repo(
97 db_session,
98 owner="pub-repo-user",
99 owner_user_id=profile.user_id,
100 slug="private-one",
101 visibility="private",
102 )
103
104 repos = await musehub_profile.get_public_repos(db_session, profile.user_id)
105 slugs = [r.slug for r in repos]
106 assert "public-one" in slugs
107 assert "private-one" not in slugs
108
109
110 @pytest.mark.anyio
111 async def test_get_public_repos_empty_for_no_repos(db_session: AsyncSession) -> None:
112 profile = await create_profile(db_session, username="no-repos-user")
113 repos = await musehub_profile.get_public_repos(db_session, profile.user_id)
114 assert repos == []
115
116
117 # ---------------------------------------------------------------------------
118 # get_contribution_graph
119 # ---------------------------------------------------------------------------
120
121 @pytest.mark.anyio
122 async def test_contribution_graph_returns_52_weeks(db_session: AsyncSession) -> None:
123 profile = await create_profile(db_session, username="graph-user")
124 graph = await musehub_profile.get_contribution_graph(db_session, profile.user_id)
125 # 52 weeks × 7 days = 364, but the implementation may include today making it 365
126 assert len(graph) in (364, 365)
127
128
129 @pytest.mark.anyio
130 async def test_contribution_graph_all_zero_for_no_commits(db_session: AsyncSession) -> None:
131 profile = await create_profile(db_session, username="zero-commits-user")
132 graph = await musehub_profile.get_contribution_graph(db_session, profile.user_id)
133 assert all(day.count == 0 for day in graph)
134
135
136 # ---------------------------------------------------------------------------
137 # get_session_credits
138 # ---------------------------------------------------------------------------
139
140 @pytest.mark.anyio
141 async def test_session_credits_zero_baseline(db_session: AsyncSession) -> None:
142 profile = await create_profile(db_session, username="credit-user")
143 credits = await musehub_profile.get_session_credits(db_session, profile.user_id)
144 assert credits == 0
145
146
147 # ---------------------------------------------------------------------------
148 # get_full_profile
149 # ---------------------------------------------------------------------------
150
151 @pytest.mark.anyio
152 async def test_get_full_profile_returns_structured_response(db_session: AsyncSession) -> None:
153 profile = await create_profile(
154 db_session,
155 username="full-profile-user",
156 bio="Full profile bio",
157 display_name="Full User",
158 )
159 result = await musehub_profile.get_full_profile(db_session, "full-profile-user")
160
161 assert result is not None
162 assert result.username == "full-profile-user"
163 assert result.bio == "Full profile bio"
164 assert result.display_name == "Full User"
165 assert isinstance(result.repos, list)
166 assert isinstance(result.contribution_graph, list)
167 assert result.session_credits == 0
168
169
170 @pytest.mark.anyio
171 async def test_get_full_profile_missing_returns_none(db_session: AsyncSession) -> None:
172 result = await musehub_profile.get_full_profile(db_session, "nobody-at-all")
173 assert result is None