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

Commit 037ce46

Browse files
committed
refactor (tests): move shared test code to ... shared.py
1 parent db236c5 commit 037ce46

File tree

6 files changed

+219
-220
lines changed

6 files changed

+219
-220
lines changed

tests/application.py

Lines changed: 7 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,21 @@
1-
from collections import defaultdict
1+
import os
2+
import sys
23
from collections.abc import AsyncIterator
34
from contextlib import asynccontextmanager
4-
from typing import Any, Literal, Self
5+
from typing import Any
56

67
from fastapi import FastAPI
7-
from pydantic import BaseModel, Field, model_validator
8+
9+
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
810

911
from stapi_fastapi.models.conformance import CORE
10-
from stapi_fastapi.models.opportunity import (
11-
OpportunityProperties,
12-
)
13-
from stapi_fastapi.models.order import (
14-
Order,
15-
OrderParameters,
16-
OrderStatus,
17-
)
18-
from stapi_fastapi.models.product import (
19-
Product,
20-
Provider,
21-
ProviderRole,
22-
)
2312
from stapi_fastapi.routers.root_router import RootRouter
24-
25-
from .backends import (
26-
mock_create_order,
13+
from tests.backends import (
2714
mock_get_order,
2815
mock_get_order_statuses,
2916
mock_get_orders,
30-
mock_search_opportunities,
31-
)
32-
33-
34-
class InMemoryOrderDB:
35-
def __init__(self) -> None:
36-
self._orders: dict[str, Order] = {}
37-
self._statuses: dict[str, list[OrderStatus]] = defaultdict(list)
38-
39-
40-
class MyProductConstraints(BaseModel):
41-
off_nadir: int
42-
43-
44-
class OffNadirRange(BaseModel):
45-
minimum: int = Field(ge=0, le=45)
46-
maximum: int = Field(ge=0, le=45)
47-
48-
@model_validator(mode="after")
49-
def validate_range(self) -> Self:
50-
if self.minimum > self.maximum:
51-
raise ValueError("range minimum cannot be greater than maximum")
52-
return self
53-
54-
55-
class MyOpportunityProperties(OpportunityProperties):
56-
off_nadir: OffNadirRange
57-
vehicle_id: list[Literal[1, 2, 5, 7, 8]]
58-
platform: Literal["platform_id"]
59-
60-
61-
class MyOrderParameters(OrderParameters):
62-
s3_path: str | None = None
63-
64-
65-
provider = Provider(
66-
name="Test Provider",
67-
description="A provider for Test data",
68-
roles=[ProviderRole.producer], # Example role
69-
url="https://test-provider.example.com", # Must be a valid URL
70-
)
71-
72-
mock_product_test_spotlight = Product(
73-
id="test-spotlight",
74-
title="Test Spotlight Product",
75-
description="Test product for test spotlight",
76-
license="CC-BY-4.0",
77-
keywords=["test", "satellite"],
78-
providers=[provider],
79-
links=[],
80-
create_order=mock_create_order,
81-
search_opportunities=mock_search_opportunities,
82-
constraints=MyProductConstraints,
83-
opportunity_properties=MyOpportunityProperties,
84-
order_parameters=MyOrderParameters,
8517
)
18+
from tests.shared import InMemoryOrderDB, mock_product_test_spotlight
8619

8720

8821
@asynccontextmanager

tests/conftest.py

Lines changed: 13 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
11
from collections.abc import AsyncIterator, Iterator
22
from contextlib import asynccontextmanager
3-
from datetime import datetime, timedelta, timezone
43
from typing import Any, Callable
54
from urllib.parse import urljoin
6-
from uuid import uuid4
75

86
import pytest
9-
from fastapi import FastAPI, status
7+
from fastapi import FastAPI
108
from fastapi.testclient import TestClient
11-
from geojson_pydantic import Point
12-
from geojson_pydantic.types import Position2D
13-
from httpx import Response
14-
from pytest import fail
159

1610
from stapi_fastapi.models.opportunity import (
1711
Opportunity,
@@ -21,49 +15,35 @@
2115
)
2216
from stapi_fastapi.routers.root_router import RootRouter
2317

24-
from .application import (
25-
InMemoryOrderDB,
26-
MyOpportunityProperties,
27-
MyOrderParameters,
28-
MyProductConstraints,
29-
OffNadirRange,
30-
mock_create_order,
18+
from .backends import (
3119
mock_get_order,
3220
mock_get_order_statuses,
3321
mock_get_orders,
22+
)
23+
from .shared import (
24+
InMemoryOrderDB,
25+
create_mock_opportunity,
26+
find_link,
27+
mock_product_test_satellite_provider,
3428
mock_product_test_spotlight,
35-
mock_search_opportunities,
36-
provider,
3729
)
38-
from .shared import find_link
3930

4031

4132
@pytest.fixture(scope="session")
4233
def base_url() -> Iterator[str]:
4334
yield "http://stapiserver"
4435

4536

46-
mock_product_test_satellite_provider = Product(
47-
id="test-satellite-provider",
48-
title="Satellite Product",
49-
description="A product by a satellite provider",
50-
license="CC-BY-4.0",
51-
keywords=["test", "satellite", "provider"],
52-
providers=[provider],
53-
links=[],
54-
create_order=mock_create_order,
55-
search_opportunities=mock_search_opportunities,
56-
constraints=MyProductConstraints,
57-
opportunity_properties=MyOpportunityProperties,
58-
order_parameters=MyOrderParameters,
59-
)
60-
61-
6237
@pytest.fixture
6338
def mock_products() -> list[Product]:
6439
return [mock_product_test_spotlight, mock_product_test_satellite_provider]
6540

6641

42+
@pytest.fixture
43+
def mock_opportunities() -> list[Opportunity]:
44+
return [create_mock_opportunity()]
45+
46+
6747
@pytest.fixture
6848
def stapi_client(
6949
mock_products: list[Product],
@@ -134,99 +114,3 @@ def _assert_link(
134114
assert link["href"] == url_for(path)
135115

136116
return _assert_link
137-
138-
139-
@pytest.fixture
140-
def mock_opportunities() -> list[Opportunity]:
141-
"""Fixture to create mock data for Opportunities for `test-spotlight-1`."""
142-
now = datetime.now(timezone.utc) # Use timezone-aware datetime
143-
start = now
144-
end = start + timedelta(days=5)
145-
146-
# Create a list of mock opportunities for the given product
147-
return [
148-
Opportunity(
149-
id=str(uuid4()),
150-
type="Feature",
151-
geometry=Point(
152-
type="Point",
153-
coordinates=Position2D(longitude=0.0, latitude=0.0),
154-
),
155-
properties=MyOpportunityProperties(
156-
product_id="xyz123",
157-
datetime=(start, end),
158-
off_nadir=OffNadirRange(minimum=20, maximum=22),
159-
vehicle_id=[1],
160-
platform="platform_id",
161-
other_thing="abcd1234",
162-
),
163-
),
164-
]
165-
166-
167-
def pagination_tester(
168-
stapi_client: TestClient,
169-
endpoint: str,
170-
method: str,
171-
limit: int,
172-
target: str,
173-
expected_returns: list,
174-
body: dict | None = None,
175-
) -> None:
176-
retrieved = []
177-
178-
res = make_request(stapi_client, endpoint, method, body, None, limit)
179-
assert res.status_code == status.HTTP_200_OK
180-
resp_body = res.json()
181-
182-
assert len(resp_body[target]) <= limit
183-
retrieved.extend(resp_body[target])
184-
next_url = next((d["href"] for d in resp_body["links"] if d["rel"] == "next"), None)
185-
186-
while next_url:
187-
url = next_url
188-
if method == "POST":
189-
body = next(
190-
(d["body"] for d in resp_body["links"] if d["rel"] == "next"), None
191-
)
192-
193-
res = make_request(stapi_client, url, method, body, next_url, limit)
194-
assert res.status_code == status.HTTP_200_OK
195-
assert len(resp_body[target]) <= limit
196-
resp_body = res.json()
197-
retrieved.extend(resp_body[target])
198-
199-
# get url w/ query params for next call if exists, and POST body if necessary
200-
if resp_body["links"]:
201-
next_url = next(
202-
(d["href"] for d in resp_body["links"] if d["rel"] == "next"), None
203-
)
204-
else:
205-
next_url = None
206-
207-
assert len(retrieved) == len(expected_returns)
208-
assert retrieved == expected_returns
209-
210-
211-
def make_request(
212-
stapi_client: TestClient,
213-
endpoint: str,
214-
method: str,
215-
body: dict | None,
216-
next_token: str | None,
217-
limit: int,
218-
) -> Response:
219-
"""request wrapper for pagination tests"""
220-
221-
match method:
222-
case "GET":
223-
if next_token: # extract pagination token
224-
next_token = next_token.split("next=")[1]
225-
params = {"next": next_token, "limit": limit}
226-
res = stapi_client.get(endpoint, params=params)
227-
case "POST":
228-
res = stapi_client.post(endpoint, json=body)
229-
case _:
230-
fail(f"method {method} not supported in make request")
231-
232-
return res

0 commit comments

Comments
 (0)