Skip to content

Commit d7eb85a

Browse files
refactor: minor refactoring, increase test coverage for query iterator/builder
1 parent 0ac5470 commit d7eb85a

File tree

4 files changed

+394
-1
lines changed

4 files changed

+394
-1
lines changed

tests/test_async_query_iterator.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,54 @@ async def test_async_iterate_entities_basic(
8989
# Verify all entity keys are present and unique
9090
result_keys = [entity.key for entity in entities]
9191
assert set(result_keys) == set(expected_keys)
92+
93+
@pytest.mark.asyncio
94+
async def test_async_iterate_entities_empty(
95+
self, async_arkiv_client_http: AsyncArkiv
96+
) -> None:
97+
"""Test iteration over empty result set."""
98+
# Create some entities (to ensure the query mechanism works)
99+
num_entities = 5
100+
await create_test_entities(async_arkiv_client_http, num_entities)
101+
102+
# Query for non-existent batch_id
103+
query = 'batch_id = "does-not-exist"'
104+
options = QueryOptions(attributes=KEY | ATTRIBUTES, max_results_per_page=10)
105+
106+
# Collect results - should be empty
107+
entities = []
108+
async for entity in async_arkiv_client_http.arkiv.query_entities(
109+
query=query, options=options
110+
):
111+
entities.append(entity)
112+
113+
assert len(entities) == 0
114+
115+
@pytest.mark.asyncio
116+
async def test_async_iterate_entities_max_results_across_pages(
117+
self, async_arkiv_client_http: AsyncArkiv
118+
) -> None:
119+
"""Test max_results limits iteration across multiple pages."""
120+
# Create 10 entities
121+
num_entities = 10
122+
batch_id, _ = await create_test_entities(async_arkiv_client_http, num_entities)
123+
124+
# Query with max_results=7 and page size of 3
125+
# Should iterate across 3 pages (3+3+1) and stop at 7
126+
query = f'batch_id = "{batch_id}"'
127+
options = QueryOptions(
128+
attributes=KEY | ATTRIBUTES,
129+
max_results=7,
130+
max_results_per_page=3,
131+
)
132+
133+
entities = []
134+
async for entity in async_arkiv_client_http.arkiv.query_entities(
135+
query=query, options=options
136+
):
137+
entities.append(entity)
138+
139+
assert len(entities) == 7
140+
for entity in entities:
141+
assert entity.attributes is not None
142+
assert entity.attributes["batch_id"] == batch_id

tests/test_query_builder.py

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,12 +758,91 @@ def test_method_chaining(self, arkiv_client_http: Arkiv) -> None:
758758
builder4 = builder.at_block(12345)
759759
assert builder4 is builder
760760

761+
def test_limit(self, arkiv_client_http: Arkiv) -> None:
762+
"""Test .limit() restricts total results returned."""
763+
batch_id, _ = create_test_entities(arkiv_client_http, 3) # 3 names x 3 seq = 9
764+
765+
# Limit to 5 results
766+
results = list(
767+
arkiv_client_http.arkiv.select(KEY, ATTRIBUTES)
768+
.where(f'batch_id = "{batch_id}"')
769+
.limit(5)
770+
.fetch()
771+
)
772+
773+
assert len(results) == 5
774+
775+
def test_limit_with_order_by(self, arkiv_client_http: Arkiv) -> None:
776+
"""Test .limit() with ORDER BY returns top N sorted results."""
777+
batch_id, _ = create_test_entities(arkiv_client_http, 3) # 3 names x 3 seq = 9
778+
779+
# Get top 3 by sequence descending
780+
results = list(
781+
arkiv_client_http.arkiv.select(KEY, ATTRIBUTES)
782+
.where(f'batch_id = "{batch_id}"')
783+
.order_by(IntSort("sequence", DESC))
784+
.limit(3)
785+
.fetch()
786+
)
787+
788+
assert len(results) == 3
789+
# All should have sequence = 3 (highest)
790+
for entity in results:
791+
assert entity.attributes is not None
792+
assert entity.attributes["sequence"] == 3
793+
794+
def test_limit_exceeds_total(self, arkiv_client_http: Arkiv) -> None:
795+
"""Test .limit() greater than total returns all results."""
796+
batch_id, _ = create_test_entities(arkiv_client_http, 2) # 2 names x 3 seq = 6
797+
798+
# Limit to 100 but only 6 exist
799+
results = list(
800+
arkiv_client_http.arkiv.select(KEY, ATTRIBUTES)
801+
.where(f'batch_id = "{batch_id}"')
802+
.limit(100)
803+
.fetch()
804+
)
805+
806+
assert len(results) == 6
807+
808+
def test_max_page_size(self, arkiv_client_http: Arkiv) -> None:
809+
"""Test .max_page_size() controls entities per page."""
810+
batch_id, _ = create_test_entities(arkiv_client_http, 3) # 3 names x 3 seq = 9
811+
812+
# Use small page size - should still get all results via pagination
813+
results = list(
814+
arkiv_client_http.arkiv.select(KEY, ATTRIBUTES)
815+
.where(f'batch_id = "{batch_id}"')
816+
.max_page_size(2)
817+
.fetch()
818+
)
819+
820+
# All 9 results should be returned despite small page size
821+
assert len(results) == 9
822+
823+
def test_limit_and_max_page_size_combined(self, arkiv_client_http: Arkiv) -> None:
824+
"""Test .limit() and .max_page_size() work together correctly."""
825+
batch_id, _ = create_test_entities(arkiv_client_http, 3) # 3 names x 3 seq = 9
826+
827+
# Limit to 5, page size of 2 (should fetch 3 pages: 2+2+1)
828+
results = list(
829+
arkiv_client_http.arkiv.select(KEY, ATTRIBUTES)
830+
.where(f'batch_id = "{batch_id}"')
831+
.limit(5)
832+
.max_page_size(2)
833+
.fetch()
834+
)
835+
836+
assert len(results) == 5
837+
761838

762839
class TestAsyncQueryBuilder:
763840
"""Tests for async AsyncQueryBuilder fluent API."""
764841

765842
@pytest.mark.asyncio
766-
async def test_select_all_fields(self, async_arkiv_client_http: AsyncArkiv) -> None:
843+
async def test_async_select_all_fields(
844+
self, async_arkiv_client_http: AsyncArkiv
845+
) -> None:
767846
"""Test async .select() with no args selects all fields."""
768847
# Create entities using sync client first (from fixture's underlying connection)
769848
# For async tests, we need to use the async client for everything

tests/test_query_iterator.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,120 @@ def test_iterate_entities_exactly_page(self, arkiv_client_http: Arkiv) -> None:
197197
# Verify all entity keys are present and unique
198198
result_keys = [entity.key for entity in entities]
199199
assert set(result_keys) == set(expected_keys)
200+
201+
def test_iterate_entities_max_results_within_single_page(
202+
self, arkiv_client_http: Arkiv
203+
) -> None:
204+
"""Test max_results limits iteration within a single page."""
205+
# Create 10 entities
206+
num_entities = 10
207+
batch_id, _ = create_test_entities(arkiv_client_http, num_entities)
208+
209+
# Query with max_results=3 and large page size
210+
# Should stop after 3 entities without fetching more
211+
query = f'batch_id = "{batch_id}"'
212+
options = QueryOptions(
213+
attributes=KEY | ATTRIBUTES,
214+
max_results=3,
215+
max_results_per_page=100,
216+
)
217+
218+
iterator = arkiv_client_http.arkiv.query_entities(query=query, options=options)
219+
entities = list(iterator)
220+
221+
assert len(entities) == 3
222+
for entity in entities:
223+
assert entity.attributes is not None
224+
assert entity.attributes["batch_id"] == batch_id
225+
226+
def test_iterate_entities_max_results_across_pages(
227+
self, arkiv_client_http: Arkiv
228+
) -> None:
229+
"""Test max_results limits iteration across multiple pages."""
230+
# Create 10 entities
231+
num_entities = 10
232+
batch_id, _ = create_test_entities(arkiv_client_http, num_entities)
233+
234+
# Query with max_results=7 and page size of 3
235+
# Should iterate across 3 pages (3+3+1) and stop at 7
236+
query = f'batch_id = "{batch_id}"'
237+
options = QueryOptions(
238+
attributes=KEY | ATTRIBUTES,
239+
max_results=7,
240+
max_results_per_page=3,
241+
)
242+
243+
iterator = arkiv_client_http.arkiv.query_entities(query=query, options=options)
244+
entities = list(iterator)
245+
246+
assert len(entities) == 7
247+
for entity in entities:
248+
assert entity.attributes is not None
249+
assert entity.attributes["batch_id"] == batch_id
250+
251+
def test_iterate_entities_max_results_equals_total(
252+
self, arkiv_client_http: Arkiv
253+
) -> None:
254+
"""Test max_results equal to total matching entities."""
255+
# Create 5 entities
256+
num_entities = 5
257+
batch_id, expected_keys = create_test_entities(arkiv_client_http, num_entities)
258+
259+
# Query with max_results=5 (exactly matching total)
260+
query = f'batch_id = "{batch_id}"'
261+
options = QueryOptions(
262+
attributes=KEY | ATTRIBUTES,
263+
max_results=5,
264+
max_results_per_page=10,
265+
)
266+
267+
iterator = arkiv_client_http.arkiv.query_entities(query=query, options=options)
268+
entities = list(iterator)
269+
270+
assert len(entities) == 5
271+
result_keys = [entity.key for entity in entities]
272+
assert set(result_keys) == set(expected_keys)
273+
274+
def test_iterate_entities_max_results_exceeds_total(
275+
self, arkiv_client_http: Arkiv
276+
) -> None:
277+
"""Test max_results greater than total matching entities."""
278+
# Create 5 entities
279+
num_entities = 5
280+
batch_id, expected_keys = create_test_entities(arkiv_client_http, num_entities)
281+
282+
# Query with max_results=100 (more than available)
283+
query = f'batch_id = "{batch_id}"'
284+
options = QueryOptions(
285+
attributes=KEY | ATTRIBUTES,
286+
max_results=100,
287+
max_results_per_page=10,
288+
)
289+
290+
iterator = arkiv_client_http.arkiv.query_entities(query=query, options=options)
291+
entities = list(iterator)
292+
293+
# Should get all 5 entities (not artificially limited)
294+
assert len(entities) == 5
295+
result_keys = [entity.key for entity in entities]
296+
assert set(result_keys) == set(expected_keys)
297+
298+
def test_iterate_entities_max_results_zero(self, arkiv_client_http: Arkiv) -> None:
299+
"""Test max_results=0 returns no entities."""
300+
# Create 5 entities
301+
num_entities = 5
302+
batch_id, _ = create_test_entities(arkiv_client_http, num_entities)
303+
304+
# Query with max_results=0
305+
query = f'batch_id = "{batch_id}"'
306+
options = QueryOptions(
307+
attributes=KEY | ATTRIBUTES,
308+
max_results=0,
309+
max_results_per_page=10,
310+
)
311+
312+
iterator = arkiv_client_http.arkiv.query_entities(query=query, options=options)
313+
entities = list(iterator)
314+
315+
# Should return no entities
316+
assert len(entities) == 0

0 commit comments

Comments
 (0)