Skip to content
This repository was archived by the owner on Apr 2, 2025. It is now read-only.

Commit b775a1e

Browse files
committed
tests: add pagination tests for async search, fix a few bugs
1 parent d2b849a commit b775a1e

File tree

3 files changed

+104
-21
lines changed

3 files changed

+104
-21
lines changed

src/stapi_fastapi/routers/product_router.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,10 @@ async def search_opportunities_async(
300300
) -> JSONResponse:
301301
match await self.product._search_opportunities_async(self, search, request):
302302
case Success(search_record):
303-
self.root_router.add_opportunity_search_record_self_link(
304-
search_record, request
303+
search_record.links.append(
304+
self.root_router.opportunity_search_record_self_link(
305+
search_record, request
306+
)
305307
)
306308
headers = {}
307309
headers["Location"] = str(

src/stapi_fastapi/routers/root_router.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -376,11 +376,15 @@ async def get_opportunity_search_records(
376376
match await self._get_opportunity_search_records(next, limit, request):
377377
case Success((records, Some(pagination_token))):
378378
for record in records:
379-
self.add_opportunity_search_record_self_link(record, request)
380-
links.append(self.pagination_link(request, pagination_token))
379+
record.links.append(
380+
self.opportunity_search_record_self_link(record, request)
381+
)
382+
links.append(self.pagination_link(request, pagination_token, limit))
381383
case Success((records, Nothing)): # noqa: F841
382384
for record in records:
383-
self.add_opportunity_search_record_self_link(record, request)
385+
record.links.append(
386+
self.opportunity_search_record_self_link(record, request)
387+
)
384388
case Failure(ValueError()):
385389
raise NotFoundException(detail="Error finding pagination token")
386390
case Failure(e):
@@ -404,7 +408,9 @@ async def get_opportunity_search_record(
404408
"""
405409
match await self._get_opportunity_search_record(search_record_id, request):
406410
case Success(Some(search_record)):
407-
self.add_opportunity_search_record_self_link(search_record, request)
411+
search_record.links.append(
412+
self.opportunity_search_record_self_link(search_record, request)
413+
)
408414
return search_record
409415
case Success(Maybe.empty):
410416
raise NotFoundException("Opportunity Search Record not found")
@@ -429,19 +435,17 @@ def generate_opportunity_search_record_href(
429435
search_record_id=search_record_id,
430436
)
431437

432-
def add_opportunity_search_record_self_link(
438+
def opportunity_search_record_self_link(
433439
self: Self, opportunity_search_record: OpportunitySearchRecord, request: Request
434-
) -> None:
435-
opportunity_search_record.links.append(
436-
Link(
437-
href=str(
438-
self.generate_opportunity_search_record_href(
439-
request, opportunity_search_record.id
440-
)
441-
),
442-
rel="self",
443-
type=TYPE_JSON,
444-
)
440+
) -> Link:
441+
return Link(
442+
href=str(
443+
self.generate_opportunity_search_record_href(
444+
request, opportunity_search_record.id
445+
)
446+
),
447+
rel="self",
448+
type=TYPE_JSON,
445449
)
446450

447451
@property

tests/test_opportunity_async.py

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
from datetime import datetime, timezone
1+
from datetime import UTC, datetime, timedelta, timezone
22
from typing import Any, Callable
33
from uuid import uuid4
44

55
import pytest
6+
from fastapi import status
67
from fastapi.testclient import TestClient
78

89
from stapi_fastapi.models.opportunity import (
@@ -17,11 +18,13 @@
1718
from .shared import (
1819
create_mock_opportunity,
1920
find_link,
21+
pagination_tester,
2022
product_test_spotlight,
2123
product_test_spotlight_async_opportunity,
2224
product_test_spotlight_sync_async_opportunity,
2325
product_test_spotlight_sync_opportunity,
2426
)
27+
from .test_datetime_interval import rfc3339_strftime
2528

2629

2730
@pytest.mark.parametrize("mock_products", [[product_test_spotlight]])
@@ -297,5 +300,79 @@ def test_new_search_location_header_matches_self_link(
297300
assert search_response.headers["Location"] == str(link["href"])
298301

299302

300-
# Pagination test for the OpportunitySearchRecrods returned from the /searches/opportunities
301-
# endpoint on the root router
303+
@pytest.mark.parametrize("mock_products", [[product_test_spotlight_async_opportunity]])
304+
def test_bad_ids(stapi_client_async_opportunity: TestClient) -> None:
305+
search_record_id = "bad_id"
306+
res = stapi_client_async_opportunity.get(
307+
f"/searches/opportunities/{search_record_id}"
308+
)
309+
assert res.status_code == status.HTTP_404_NOT_FOUND
310+
311+
product_id = "test-spotlight"
312+
opportunity_collection_id = "bad_id"
313+
res = stapi_client_async_opportunity.get(
314+
f"/products/{product_id}/opportunities/{opportunity_collection_id}"
315+
)
316+
assert res.status_code == status.HTTP_404_NOT_FOUND
317+
318+
319+
@pytest.fixture
320+
def setup_search_record_pagination(
321+
stapi_client_async_opportunity: TestClient,
322+
mock_products: list[Product],
323+
) -> list[dict[str, Any]]:
324+
product_id = "test-spotlight"
325+
search_records = []
326+
for _ in range(3):
327+
now = datetime.now(UTC)
328+
end = now + timedelta(days=5)
329+
format = "%Y-%m-%dT%H:%M:%S.%f%z"
330+
start_string = rfc3339_strftime(now, format)
331+
end_string = rfc3339_strftime(end, format)
332+
333+
opportunity_request = {
334+
"geometry": {
335+
"type": "Point",
336+
"coordinates": [0, 0],
337+
},
338+
"datetime": f"{start_string}/{end_string}",
339+
"filter": {
340+
"op": "and",
341+
"args": [
342+
{"op": ">", "args": [{"property": "off_nadir"}, 0]},
343+
{"op": "<", "args": [{"property": "off_nadir"}, 45]},
344+
],
345+
},
346+
}
347+
348+
response = stapi_client_async_opportunity.post(
349+
f"/products/{product_id}/opportunities", json=opportunity_request
350+
)
351+
assert response.status_code == 201
352+
353+
body = response.json()
354+
search_records.append(body)
355+
356+
return search_records
357+
358+
359+
@pytest.mark.parametrize("limit", [0, 1, 2, 4])
360+
@pytest.mark.parametrize("mock_products", [[product_test_spotlight_async_opportunity]])
361+
def test_get_search_records_pagination(
362+
stapi_client_async_opportunity: TestClient,
363+
mock_products: list[Product],
364+
setup_search_record_pagination: list[dict[str, Any]],
365+
limit: int,
366+
) -> None:
367+
expected_returns = []
368+
if limit > 0:
369+
expected_returns = setup_search_record_pagination
370+
371+
pagination_tester(
372+
stapi_client=stapi_client_async_opportunity,
373+
url="/searches/opportunities",
374+
method="GET",
375+
limit=limit,
376+
target="search_records",
377+
expected_returns=expected_returns,
378+
)

0 commit comments

Comments
 (0)