gabriel / musehub public

test_fleet_pagination.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 """TDD — fleet pagination: offset/limit, total count, first/last/prev/next state."""
2 from __future__ import annotations
3
4 import math
5 import pytest
6 from datetime import datetime, timezone
7 from sqlalchemy.ext.asyncio import AsyncSession
8
9 from musehub.db.musehub_repo_models import MusehubCommit, MusehubCommitRef
10 from tests.factories import create_repo
11 from muse.core.types import blob_id
12
13
14 def _utc() -> datetime:
15 return datetime.now(tz=timezone.utc)
16
17
18 async def _add_commit(
19 session: AsyncSession,
20 repo_id: str,
21 seed: str,
22 agent_id: str = "claude-code",
23 model_id: str = "claude-sonnet-4-6",
24 ) -> None:
25 row = MusehubCommit(
26 commit_id=blob_id(seed.encode()),
27 branch="dev",
28 parent_ids=[],
29 message=f"feat: {seed}",
30 author="gabriel",
31 timestamp=_utc(),
32 agent_id=agent_id,
33 model_id=model_id,
34 )
35 session.add(row)
36 session.add(MusehubCommitRef(repo_id=repo_id, commit_id=row.commit_id))
37 await session.commit()
38
39
40 _IDENTITY = {
41 "handle": "gabriel",
42 "type": "human",
43 "user_id": None,
44 }
45
46 # ---------------------------------------------------------------------------
47 # P1 — first page returns up to PAGE_SIZE agents, next_cursor set when more exist
48 # ---------------------------------------------------------------------------
49
50 @pytest.mark.asyncio
51 async def test_p1_first_page_returns_page_size_and_next_cursor(
52 db_session: AsyncSession,
53 ) -> None:
54 from musehub.api.routes.musehub.ui_user_profile import _fetch_agent_fleet, _FLEET_PAGE_SIZE
55
56 repo = await create_repo(db_session, owner="gabriel", visibility="public")
57
58 # Create PAGE_SIZE + 1 distinct agents
59 for i in range(_FLEET_PAGE_SIZE + 1):
60 await _add_commit(db_session, repo.repo_id, f"p1-c{i}", agent_id=f"agent-{i:02d}")
61
62 result = await _fetch_agent_fleet(db_session, _IDENTITY)
63
64 assert len(result["agents"]) == _FLEET_PAGE_SIZE
65 assert result["next_cursor"] == _FLEET_PAGE_SIZE
66
67
68 # ---------------------------------------------------------------------------
69 # P2 — last page has no next_cursor
70 # ---------------------------------------------------------------------------
71
72 @pytest.mark.asyncio
73 async def test_p2_last_page_has_no_next_cursor(
74 db_session: AsyncSession,
75 ) -> None:
76 from musehub.api.routes.musehub.ui_user_profile import _fetch_agent_fleet, _FLEET_PAGE_SIZE
77
78 repo = await create_repo(db_session, owner="gabriel", visibility="public")
79
80 for i in range(_FLEET_PAGE_SIZE + 1):
81 await _add_commit(db_session, repo.repo_id, f"p2-c{i}", agent_id=f"agent-{i:02d}")
82
83 result = await _fetch_agent_fleet(db_session, _IDENTITY, offset=_FLEET_PAGE_SIZE)
84
85 assert len(result["agents"]) == 1
86 assert result["next_cursor"] is None
87
88
89 # ---------------------------------------------------------------------------
90 # P3 — total_agents count is always the full fleet size regardless of page
91 # ---------------------------------------------------------------------------
92
93 @pytest.mark.asyncio
94 async def test_p3_total_agents_reflects_full_fleet(
95 db_session: AsyncSession,
96 ) -> None:
97 from musehub.api.routes.musehub.ui_user_profile import _fetch_agent_fleet, _FLEET_PAGE_SIZE
98
99 repo = await create_repo(db_session, owner="gabriel", visibility="public")
100 n = _FLEET_PAGE_SIZE + 3
101
102 for i in range(n):
103 await _add_commit(db_session, repo.repo_id, f"p3-c{i}", agent_id=f"agent-{i:02d}")
104
105 page1 = await _fetch_agent_fleet(db_session, _IDENTITY, offset=0)
106 page2 = await _fetch_agent_fleet(db_session, _IDENTITY, offset=_FLEET_PAGE_SIZE)
107
108 assert page1["total_agents"] == n
109 assert page2["total_agents"] == n
110
111
112 # ---------------------------------------------------------------------------
113 # P4 — total_pages derived correctly from total_agents and PAGE_SIZE
114 # ---------------------------------------------------------------------------
115
116 @pytest.mark.asyncio
117 async def test_p4_total_pages_rounds_up(
118 db_session: AsyncSession,
119 ) -> None:
120 from musehub.api.routes.musehub.ui_user_profile import _fetch_agent_fleet, _FLEET_PAGE_SIZE
121
122 repo = await create_repo(db_session, owner="gabriel", visibility="public")
123 n = _FLEET_PAGE_SIZE + 1 # exactly 2 pages
124
125 for i in range(n):
126 await _add_commit(db_session, repo.repo_id, f"p4-c{i}", agent_id=f"agent-{i:02d}")
127
128 result = await _fetch_agent_fleet(db_session, _IDENTITY)
129
130 assert result["total_pages"] == math.ceil(n / _FLEET_PAGE_SIZE)
131
132
133 # ---------------------------------------------------------------------------
134 # P5 — current_page derived from offset
135 # ---------------------------------------------------------------------------
136
137 @pytest.mark.asyncio
138 async def test_p5_current_page_reflects_offset(
139 db_session: AsyncSession,
140 ) -> None:
141 from musehub.api.routes.musehub.ui_user_profile import _fetch_agent_fleet, _FLEET_PAGE_SIZE
142
143 repo = await create_repo(db_session, owner="gabriel", visibility="public")
144
145 for i in range(_FLEET_PAGE_SIZE * 3):
146 await _add_commit(db_session, repo.repo_id, f"p5-c{i}", agent_id=f"agent-{i:02d}")
147
148 p1 = await _fetch_agent_fleet(db_session, _IDENTITY, offset=0)
149 p2 = await _fetch_agent_fleet(db_session, _IDENTITY, offset=_FLEET_PAGE_SIZE)
150 p3 = await _fetch_agent_fleet(db_session, _IDENTITY, offset=_FLEET_PAGE_SIZE * 2)
151
152 assert p1["current_page"] == 1
153 assert p2["current_page"] == 2
154 assert p3["current_page"] == 3
155
156
157 # ---------------------------------------------------------------------------
158 # P6 — single page: no next_cursor, total_pages == 1
159 # ---------------------------------------------------------------------------
160
161 @pytest.mark.asyncio
162 async def test_p6_single_page_fleet(
163 db_session: AsyncSession,
164 ) -> None:
165 from musehub.api.routes.musehub.ui_user_profile import _fetch_agent_fleet, _FLEET_PAGE_SIZE
166
167 repo = await create_repo(db_session, owner="gabriel", visibility="public")
168
169 for i in range(3):
170 await _add_commit(db_session, repo.repo_id, f"p6-c{i}", agent_id=f"agent-{i:02d}")
171
172 result = await _fetch_agent_fleet(db_session, _IDENTITY)
173
174 assert len(result["agents"]) == 3
175 assert result["next_cursor"] is None
176 assert result["total_pages"] == 1
177 assert result["current_page"] == 1