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

Commit 6fa822b

Browse files
the /products/{product_id}/opportunities endpoint is accessible
1 parent 73b9c03 commit 6fa822b

File tree

5 files changed

+70
-44
lines changed

5 files changed

+70
-44
lines changed

src/stapi_fastapi/main_router.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def __init__(
5151
self.add_api_route(
5252
"/products",
5353
self.products,
54-
methods=["GET"],
54+
methods=["GET","POST"],
5555
name=f"{self.name}:list-products",
5656
tags=["Product"],
5757
)
@@ -134,5 +134,5 @@ async def get_order(self, order_id: str, request: Request) -> Order:
134134

135135
def add_product_router(self, product_router: ProductRouter):
136136
# Give the include a prefix from the product router
137-
self.include_router(product_router, prefix=product_router.product.id)
137+
self.include_router(product_router, prefix=f"/products/{product_router.product.id}")
138138
self.product_routers[product_router.product.id] = product_router

src/stapi_fastapi/products_router.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,26 @@ def __init__(
2323
super().__init__(*args, **kwargs)
2424
self.product = product
2525

26-
# TODO: use add_api_route
27-
self.post("/opportunities", summary="Search Opportunities for the product")(self.search_opportunities)
28-
self.get("/parameters", summary="Get parameters for the product")(self.get_product_parameters)
29-
self.post("/order", summary="Create an order for the product")(self.create_order)
26+
self.add_api_route(
27+
path="/opportunities",
28+
endpoint=self.search_opportunities,
29+
methods=["POST"],
30+
summary="Search Opportunities for the product"
31+
)
32+
33+
self.add_api_route(
34+
path="/parameters",
35+
endpoint=self.get_product_parameters,
36+
methods=["GET"],
37+
summary="Get parameters for the product"
38+
)
39+
40+
self.add_api_route(
41+
path="/order",
42+
endpoint=self.create_order,
43+
methods=["POST"],
44+
summary="Create an order for the product"
45+
)
3046

3147
async def search_opportunities(self: Self, request: Request, search: OpportunityRequest):
3248
try:

tests/conftest.py

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,32 @@
1212
from stapi_fastapi.types.datetime_interval import DatetimeInterval
1313

1414
from collections.abc import Iterator
15-
from fastapi import FastAPI
1615
from fastapi.testclient import TestClient
17-
from pydantic import BaseModel
1816
from stapi_fastapi.products_router import ProductRouter
17+
from stapi_fastapi.main_router import MainRouter
1918

2019
from .backend import TestBackend
2120

21+
# Define concrete classes for Products to mock
22+
class UmbraSpotlight(Product):
23+
def search_opportunities(self, search, request):
24+
return []
25+
def create_order(self, search, request):
26+
return []
2227

23-
@pytest.fixture(scope="session")
24-
def base_url() -> Iterator[str]:
25-
yield "http://stapiserver"
26-
27-
28-
@pytest.fixture
29-
def stapi_backend() -> Iterator[TestBackend]:
30-
yield TestBackend()
28+
class UmbraSpotlightProperties(OpportunityProperties):
29+
datetime: DatetimeInterval
3130

3231
@pytest.fixture
3332
def mock_product_umbra_spotlight(mock_provider_umbra: Provider) -> Product:
3433
"""Fixture for a mock Umbra Spotlight product."""
34+
now = datetime.now(timezone.utc) # Use timezone-aware datetime
35+
start = now
36+
end = start + timedelta(days=5)
37+
datetime_interval = f"{start.isoformat()}/{end.isoformat()}"
3538

36-
return Product(
37-
id=str(uuid4()),
39+
return UmbraSpotlight(
40+
id="umbra-spotlight",
3841
title="Umbra Spotlight Product",
3942
description="Test product for umbra spotlight",
4043
license="CC-BY-4.0",
@@ -44,16 +47,27 @@ def mock_product_umbra_spotlight(mock_provider_umbra: Provider) -> Product:
4447
Link(href="http://example.com", rel="self"),
4548
Link(href="http://example.com/catalog", rel="parent"),
4649
],
47-
parameters=UmbraSpotlightProperties
50+
parameters=UmbraSpotlightProperties(
51+
datetime=datetime_interval,
52+
off_nadir=20,
53+
)
4854
)
4955

56+
@pytest.fixture(scope="session")
57+
def base_url() -> Iterator[str]:
58+
yield "http://stapiserver"
59+
60+
61+
@pytest.fixture
62+
def stapi_backend() -> Iterator[TestBackend]:
63+
yield TestBackend()
64+
5065
@pytest.fixture
51-
def stapi_client(stapi_backend, base_url: str) -> Iterator[TestClient]:
52-
app = FastAPI()
66+
def stapi_client(stapi_backend, mock_product_umbra_spotlight, base_url: str) -> Iterator[TestClient]:
67+
app = MainRouter(stapi_backend)
5368

54-
app.include_router(
55-
ProductRouter(mock_product_umbra_spotlight),
56-
prefix="",
69+
app.add_product_router(
70+
ProductRouter(mock_product_umbra_spotlight)
5771
)
5872

5973
yield TestClient(app, base_url=f"{base_url}")
@@ -71,12 +85,14 @@ def url_for(value: str) -> str:
7185

7286

7387
@pytest.fixture
74-
def products() -> Iterator[list[Product]]:
75-
class Parameters(BaseModel):
76-
pass
88+
def products(mock_product_umbra_spotlight) -> Iterator[list[Product]]:
89+
now = datetime.now(timezone.utc) # Use timezone-aware datetime
90+
start = now
91+
end = start + timedelta(days=5)
92+
datetime_interval = f"{start.isoformat()}/{end.isoformat()}"
7793

7894
yield [
79-
Product(
95+
UmbraSpotlight(
8096
id="mock:standard",
8197
description="Mock backend's standard product",
8298
license="CC0-1.0",
@@ -92,7 +108,10 @@ class Parameters(BaseModel):
92108
url="http://acme.example.com",
93109
)
94110
],
95-
parameters=Parameters,
111+
parameters=UmbraSpotlightProperties(
112+
datetime=datetime_interval,
113+
off_nadir=20,
114+
),
96115
links=[],
97116
)
98117
]
@@ -127,7 +146,6 @@ def allowed_payloads(products: list[Product]) -> Iterator[list[OpportunityReques
127146

128147
YieldFixture = Generator[T, None, None]
129148

130-
131149
def pytest_addoption(parser: Parser):
132150
parser.addoption(
133151
"--stapi-backend",
@@ -162,15 +180,6 @@ def mock_provider_umbra() -> Provider:
162180
url="https://umbra-provider.example.com" # Must be a valid URL
163181
)
164182

165-
# Define a mock OpportunityProperties class for Umbra
166-
class UmbraSpotlightProperties(OpportunityProperties):
167-
datetime: DatetimeInterval
168-
169-
@pytest.fixture
170-
def mock_products(mock_product_umbra_spotlight: Product) -> List[Product]:
171-
"""Fixture to return a list of mock products."""
172-
return [mock_product_umbra_spotlight]
173-
174183
@pytest.fixture
175184
def mock_umbra_spotlight_opportunities() -> List[Opportunity]:
176185
"""Fixture to create mock data for Opportunities for `umbra-spotlight-1`."""
@@ -190,4 +199,4 @@ def mock_umbra_spotlight_opportunities() -> List[Opportunity]:
190199
off_nadir=20,
191200
),
192201
),
193-
]
202+
]

tests/opportunity_test.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@
88

99
from .backend import TestBackend
1010

11-
@pytest.mark.parametrize("product_id", ["umbra-spotlight-1"])
11+
@pytest.mark.parametrize("product_id", ["umbra-spotlight"])
1212
def test_search_opportunities_response(
1313
product_id: str,
14-
mock_products: list[Product],
14+
products: list[Product],
1515
mock_umbra_spotlight_opportunities: List[Opportunity],
1616
stapi_backend: TestBackend,
1717
stapi_client: TestClient,
1818
):
19-
stapi_backend._products = mock_products
19+
stapi_backend._products = products
2020
stapi_backend._opportunities = mock_umbra_spotlight_opportunities
2121

2222
now = datetime.now(UTC)
2323
start = now
2424
end = start + timedelta(days=5)
2525

2626
# Create mock products and opportunities for the test
27-
mock_products[0].id = product_id
27+
products[0].id = product_id
2828

2929
# Prepare the request payload
3030
request_payload = {

tests/product_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from .warnings import StapiSpecWarning
1010

1111

12+
1213
def test_products_response(stapi_client: TestClient):
1314
res = stapi_client.get("/products")
1415

0 commit comments

Comments
 (0)