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

Commit 0d5d837

Browse files
tests: abstracted pagination testing out into a more generalized pagination_tester function
1 parent 2759ec2 commit 0d5d837

File tree

3 files changed

+113
-83
lines changed

3 files changed

+113
-83
lines changed

tests/conftest.py

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
from collections.abc import Iterator
2-
from datetime import datetime, timedelta, timezone
32
from typing import Any, Callable
43
from urllib.parse import urljoin
5-
from uuid import uuid4
64

75
import pytest
8-
from fastapi import FastAPI
6+
from fastapi import FastAPI, status
97
from fastapi.testclient import TestClient
10-
from geojson_pydantic import Point
11-
from geojson_pydantic.types import Position2D
8+
from httpx import Response
129

13-
from stapi_fastapi.models.opportunity import (
14-
Opportunity,
15-
)
1610
from stapi_fastapi.models.product import (
1711
Product,
1812
Provider,
@@ -161,35 +155,58 @@ def mock_provider() -> Provider:
161155
)
162156

163157

164-
@pytest.fixture
165-
def mock_test_spotlight_opportunities() -> list[Opportunity]:
166-
"""Fixture to create mock data for Opportunities for `test-spotlight-1`."""
167-
now = datetime.now(timezone.utc) # Use timezone-aware datetime
168-
start = now
169-
end = start + timedelta(days=5)
170-
171-
# Create a list of mock opportunities for the given product
172-
return [
173-
Opportunity(
174-
id=str(uuid4()),
175-
type="Feature",
176-
geometry=Point(
177-
type="Point",
178-
coordinates=Position2D(longitude=0.0, latitude=0.0),
179-
),
180-
properties=MyOpportunityProperties(
181-
product_id="xyz123",
182-
datetime=(start, end),
183-
off_nadir={"minimum": 20, "maximum": 22},
184-
vehicle_id=[1],
185-
platform="platform_id",
186-
),
187-
),
188-
]
189-
190-
191-
@pytest.fixture
192-
def mock_test_pagination_opportunities(
193-
mock_test_spotlight_opportunities,
194-
) -> list[Opportunity]:
195-
return [opp for opp in mock_test_spotlight_opportunities for __ in range(0, 3)]
158+
def pagination_tester(
159+
stapi_client: TestClient,
160+
endpoint: str,
161+
method: str,
162+
limit: int,
163+
target: str,
164+
expected_total_returns: int,
165+
body: dict | None = None,
166+
) -> None:
167+
retrieved = []
168+
169+
res = make_request(stapi_client, endpoint, method, body, None, limit)
170+
assert res.status_code == status.HTTP_200_OK
171+
resp_body = res.json()
172+
173+
assert len(resp_body[target]) <= limit
174+
retrieved.extend(resp_body[target])
175+
next_url = next((d["href"] for d in resp_body["links"] if d["rel"] == "next"), None)
176+
177+
while next_url:
178+
res = make_request(stapi_client, next_url, method, body, next_url, limit)
179+
assert res.status_code == status.HTTP_200_OK
180+
assert len(resp_body[target]) <= limit
181+
resp_body = res.json()
182+
retrieved.extend(resp_body[target])
183+
184+
if resp_body["links"]:
185+
next_url = next(
186+
(d["href"] for d in resp_body["links"] if d["rel"] == "next"), None
187+
)
188+
else:
189+
next_url = None
190+
191+
assert len(retrieved) == expected_total_returns
192+
193+
194+
def make_request(
195+
stapi_client: TestClient,
196+
endpoint: str,
197+
method: str,
198+
body: dict | None,
199+
next_token: str | None,
200+
limit: int,
201+
) -> Response:
202+
"""request wrapper for pagination tests"""
203+
if next_token and "next=" in next_token:
204+
next_token = next_token.split("next=")[1]
205+
params = {"next": next_token, "limit": limit}
206+
207+
if method == "GET":
208+
res = stapi_client.get(endpoint, params=params)
209+
if method == "POST":
210+
res = stapi_client.post(endpoint, json=body, params=params)
211+
212+
return res

tests/test_opportunity.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,54 @@
1-
from datetime import UTC, datetime, timedelta
1+
from datetime import UTC, datetime, timedelta, timezone
22
from typing import List
3+
from uuid import uuid4
34

45
import pytest
56
from fastapi import status
67
from fastapi.testclient import TestClient
8+
from geojson_pydantic import Point
9+
from geojson_pydantic.types import Position2D
710

811
from stapi_fastapi.models.opportunity import Opportunity, OpportunityCollection
12+
from tests.application import MyOpportunityProperties
913

1014
from .backends import MockProductBackend
1115
from .test_datetime_interval import rfc3339_strftime
1216

1317

18+
@pytest.fixture
19+
def mock_test_spotlight_opportunities() -> list[Opportunity]:
20+
"""Fixture to create mock data for Opportunities for `test-spotlight-1`."""
21+
now = datetime.now(timezone.utc) # Use timezone-aware datetime
22+
start = now
23+
end = start + timedelta(days=5)
24+
25+
# Create a list of mock opportunities for the given product
26+
return [
27+
Opportunity(
28+
id=str(uuid4()),
29+
type="Feature",
30+
geometry=Point(
31+
type="Point",
32+
coordinates=Position2D(longitude=0.0, latitude=0.0),
33+
),
34+
properties=MyOpportunityProperties(
35+
product_id="xyz123",
36+
datetime=(start, end),
37+
off_nadir={"minimum": 20, "maximum": 22},
38+
vehicle_id=[1],
39+
platform="platform_id",
40+
),
41+
),
42+
]
43+
44+
45+
@pytest.fixture
46+
def mock_test_pagination_opportunities(
47+
mock_test_spotlight_opportunities,
48+
) -> list[Opportunity]:
49+
return [opp for opp in mock_test_spotlight_opportunities for __ in range(0, 3)]
50+
51+
1452
@pytest.mark.parametrize("product_id", ["test-spotlight"])
1553
def test_search_opportunities_response(
1654
product_id: str,

tests/test_order.py

Lines changed: 17 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from httpx import Response
99

1010
from stapi_fastapi.models.order import OrderPayload, OrderStatus, OrderStatusCode
11+
from tests.conftest import pagination_tester
1112

1213
from .application import InMemoryOrderDB, MyOrderParameters
1314
from .backends import MockProductBackend
@@ -161,26 +162,15 @@ def setup_orders_pagination(stapi_client: TestClient, create_order_payloads) ->
161162
assert res.headers["Content-Type"] == "application/geo+json"
162163

163164

164-
@pytest.mark.parametrize("limit", [2])
165-
def test_order_pagination(
166-
stapi_client: TestClient, setup_orders_pagination, limit
167-
) -> None:
168-
res = stapi_client.get("/orders", params={"next": None, "limit": limit})
169-
assert res.status_code == status.HTTP_200_OK
170-
body = res.json()
171-
assert len(body["features"]) == limit
172-
next = body["links"][0]["href"]
173-
174-
while next:
175-
res = stapi_client.get(next)
176-
assert res.status_code == status.HTTP_200_OK
177-
body = res.json()
178-
assert body["features"] != []
179-
if body["links"]:
180-
assert len(body["features"]) == limit
181-
next = body["links"][0]["href"]
182-
else:
183-
break
165+
def test_order_pagination(setup_orders_pagination, stapi_client: TestClient) -> None:
166+
pagination_tester(
167+
stapi_client=stapi_client,
168+
endpoint="/orders",
169+
method="GET",
170+
limit=2,
171+
target="features",
172+
expected_total_returns=3,
173+
)
184174

185175

186176
def test_token_not_found(stapi_client: TestClient) -> None:
@@ -223,30 +213,15 @@ def test_order_status_pagination(
223213
order_db._statuses = order_statuses
224214

225215
order_id = "test_order_id"
226-
res = stapi_client.get(f"/orders/{order_id}/statuses")
227-
assert res.status_code == status.HTTP_200_OK
228216

229-
order_id = "test_order_id"
230-
res = stapi_client.get(
231-
f"/orders/{order_id}/statuses", params={"next": None, "limit": limit}
217+
pagination_tester(
218+
stapi_client=stapi_client,
219+
endpoint=f"/orders/{order_id}/statuses",
220+
method="GET",
221+
limit=2,
222+
target="statuses",
223+
expected_total_returns=3,
232224
)
233-
body = res.json()
234-
links = body["links"]
235-
for link in body["links"]:
236-
if ("rel", "next") in link.items():
237-
assert len(body["statuses"]) == limit
238-
next = link["href"]
239-
240-
while len(links) > 1:
241-
res = stapi_client.get(next)
242-
assert res.status_code == status.HTTP_200_OK
243-
body = res.json()
244-
assert body["statuses"] != []
245-
links = body["links"]
246-
for link in body["links"]:
247-
if ("rel", "next") in link.items():
248-
assert len(body["statuses"]) == limit
249-
next = body["links"][0]["href"]
250225

251226

252227
def test_get_order_statuses_bad_token(

0 commit comments

Comments
 (0)