gabriel / musehub public
test_musehub_profile_service.py python
160 lines 6.3 KB
Raw
sha256:9590cee1e0ccd6c76528f005b95d634d80f5019f0dcb7c371e149adc31d1fb65 refactor: enforce gRPC framing on all MWP wire traffic Sonnet 4.6 minor ⚠ breaking 156 days 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 async def test_create_profile_and_get_by_username(db_session: AsyncSession) -> None:
24 profile = await create_profile(db_session, username="artistone", display_name="Artist One")
25 found = await musehub_profile.get_profile_by_username(db_session, "artistone")
26 assert found is not None
27 assert found.handle == "artistone"
28 assert found.display_name == "Artist One"
29
30
31 async def test_get_profile_by_username_missing_returns_none(db_session: AsyncSession) -> None:
32 result = await musehub_profile.get_profile_by_username(db_session, "ghost-user")
33 assert result is None
34
35
36 async def test_get_profile_by_user_id(db_session: AsyncSession) -> None:
37 profile = await create_profile(db_session, username="byid-user")
38 found = await musehub_profile.get_profile_by_user_id(db_session, profile.identity_id)
39 assert found is not None
40 assert found.handle == "byid-user"
41
42
43 async def test_get_profile_by_user_id_missing_returns_none(db_session: AsyncSession) -> None:
44 result = await musehub_profile.get_profile_by_user_id(db_session, "00000000-dead-beef-0000-000000000000")
45 assert result is None
46
47
48 # ---------------------------------------------------------------------------
49 # update_profile
50 # ---------------------------------------------------------------------------
51
52 async def test_update_profile_bio(db_session: AsyncSession) -> None:
53 orm_profile = await create_profile(db_session, username="bio-user", bio="old bio")
54 await musehub_profile.update_profile(
55 db_session,
56 orm_profile,
57 ProfileUpdateRequest(bio="new bio"),
58 )
59 updated = await musehub_profile.get_profile_by_username(db_session, "bio-user")
60 assert updated is not None
61 assert updated.bio == "new bio"
62
63
64 async def test_update_profile_display_name(db_session: AsyncSession) -> None:
65 orm_profile = await create_profile(db_session, username="name-user", display_name="Old Name")
66 await musehub_profile.update_profile(
67 db_session,
68 orm_profile,
69 ProfileUpdateRequest(display_name="New Name"),
70 )
71 updated = await musehub_profile.get_profile_by_username(db_session, "name-user")
72 assert updated is not None
73 assert updated.display_name == "New Name"
74
75
76 # ---------------------------------------------------------------------------
77 # get_public_repos
78 # ---------------------------------------------------------------------------
79
80 async def test_get_public_repos_returns_public_only(db_session: AsyncSession) -> None:
81 profile = await create_profile(db_session, username="pub-repo-user")
82 await create_repo(
83 db_session,
84 owner="pub-repo-user",
85 owner_user_id=profile.identity_id,
86 slug="public-one",
87 visibility="public",
88 )
89 await create_repo(
90 db_session,
91 owner="pub-repo-user",
92 owner_user_id=profile.identity_id,
93 slug="private-one",
94 visibility="private",
95 )
96
97 repos = await musehub_profile.get_public_repos(db_session, profile.handle)
98 slugs = [r.slug for r in repos]
99 assert "public-one" in slugs
100 assert "private-one" not in slugs
101
102
103 async def test_get_public_repos_empty_for_no_repos(db_session: AsyncSession) -> None:
104 profile = await create_profile(db_session, username="no-repos-user")
105 repos = await musehub_profile.get_public_repos(db_session, profile.handle)
106 assert repos == []
107
108
109 # ---------------------------------------------------------------------------
110 # get_contribution_graph
111 # ---------------------------------------------------------------------------
112
113 async def test_contribution_graph_returns_52_weeks(db_session: AsyncSession) -> None:
114 profile = await create_profile(db_session, username="graph-user")
115 graph = await musehub_profile.get_contribution_graph(db_session, profile.handle)
116 # 52 weeks × 7 days = 364, but the implementation may include today making it 365
117 assert len(graph) in (364, 365)
118
119
120 async def test_contribution_graph_all_zero_for_no_commits(db_session: AsyncSession) -> None:
121 profile = await create_profile(db_session, username="zero-commits-user")
122 graph = await musehub_profile.get_contribution_graph(db_session, profile.handle)
123 assert all(day.count == 0 for day in graph)
124
125
126 # ---------------------------------------------------------------------------
127 # get_session_credits
128 # ---------------------------------------------------------------------------
129
130 async def test_session_credits_zero_baseline(db_session: AsyncSession) -> None:
131 profile = await create_profile(db_session, username="credit-user")
132 credits = await musehub_profile.get_session_credits(db_session, profile.handle)
133 assert credits == 0
134
135
136 # ---------------------------------------------------------------------------
137 # get_full_profile
138 # ---------------------------------------------------------------------------
139
140 async def test_get_full_profile_returns_structured_response(db_session: AsyncSession) -> None:
141 profile = await create_profile(
142 db_session,
143 username="full-profile-user",
144 bio="Full profile bio",
145 display_name="Full User",
146 )
147 result = await musehub_profile.get_full_profile(db_session, "full-profile-user")
148
149 assert result is not None
150 assert result.username == "full-profile-user"
151 assert result.bio == "Full profile bio"
152 assert result.display_name == "Full User"
153 assert isinstance(result.repos, list)
154 assert isinstance(result.contribution_graph, list)
155 assert result.session_credits == 0
156
157
158 async def test_get_full_profile_missing_returns_none(db_session: AsyncSession) -> None:
159 result = await musehub_profile.get_full_profile(db_session, "nobody-at-all")
160 assert result is None
File History 1 commit
sha256:9590cee1e0ccd6c76528f005b95d634d80f5019f0dcb7c371e149adc31d1fb65 refactor: enforce gRPC framing on all MWP wire traffic Sonnet 4.6 minor ⚠ 156 days ago