Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions stapi-fastapi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## Added

- Add constants for route names to be used in link href generation
- Conformance url to product ([#85](https://github.com/stapi-spec/pystapi/pull/85))

## Changed

Expand Down
26 changes: 26 additions & 0 deletions stapi-fastapi/src/stapi_fastapi/routers/product_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from returns.maybe import Maybe, Some
from returns.result import Failure, Success
from stapi_pydantic import (
Conformance,
JsonSchemaModel,
Link,
OpportunityCollection,
Expand All @@ -34,6 +35,7 @@
from stapi_fastapi.models.product import Product
from stapi_fastapi.responses import GeoJSONResponse
from stapi_fastapi.routers.route_names import (
CONFORMANCE,
CREATE_ORDER,
GET_CONSTRAINTS,
GET_OPPORTUNITY_COLLECTION,
Expand Down Expand Up @@ -88,6 +90,15 @@ def __init__(
tags=["Products"],
)

self.add_api_route(
path="/conformance",
endpoint=self.get_product_conformance,
name=f"{self.root_router.name}:{self.product.id}:{CONFORMANCE}",
methods=["GET"],
summary="Get conformance urls for the product",
tags=["Products"],
)

self.add_api_route(
path="/constraints",
endpoint=self.get_product_constraints,
Expand Down Expand Up @@ -179,6 +190,15 @@ def get_product(self, request: Request) -> Product:
rel="self",
type=TYPE_JSON,
),
Link(
href=str(
request.url_for(
f"{self.root_router.name}:{self.product.id}:{CONFORMANCE}",
),
),
rel="conformance",
type=TYPE_JSON,
),
Link(
href=str(
request.url_for(
Expand Down Expand Up @@ -330,6 +350,12 @@ async def search_opportunities_async(
case x:
raise AssertionError(f"Expected code to be unreachable: {x}")

def get_product_conformance(self) -> Conformance:
"""
Return conformance urls of a specific product
"""
return Conformance.model_validate({"conforms_to": self.product.conformsTo})

def get_product_constraints(self) -> JsonSchemaModel:
"""
Return supported constraints of a specific product
Expand Down
24 changes: 23 additions & 1 deletion stapi-fastapi/tests/test_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from fastapi import status
from fastapi.testclient import TestClient
from stapi_fastapi.models.product import Product
from stapi_pydantic import Conformance

from .shared import pagination_tester

Expand All @@ -19,7 +20,7 @@ def test_products_response(stapi_client: TestClient):


@pytest.mark.parametrize("product_id", ["test-spotlight"])
def test_product_response_self_link(
def test_product_response_links(
product_id: str,
stapi_client: TestClient,
assert_link,
Expand All @@ -32,12 +33,28 @@ def test_product_response_self_link(

url = "GET /products"
assert_link(url, body, "self", f"/products/{product_id}")
assert_link(
url, body, "conformance", f"/products/{product_id}/conformance"
) # https://github.com/stapi-spec/stapi-spec/issues/253
assert_link(url, body, "constraints", f"/products/{product_id}/constraints")
assert_link(url, body, "order-parameters", f"/products/{product_id}/order-parameters")
assert_link(url, body, "opportunities", f"/products/{product_id}/opportunities")
assert_link(url, body, "create-order", f"/products/{product_id}/orders", method="POST")


@pytest.mark.parametrize("product_id", ["test-spotlight"])
def test_product_conformance_response(
product_id: str,
stapi_client: TestClient,
):
res = stapi_client.get(f"/products/{product_id}/constraints")
assert res.status_code == status.HTTP_200_OK
assert res.headers["Content-Type"] == "application/json"

Conformance.model_validate(res.json())
# TODO unsure what conformance products should support, as of yet


@pytest.mark.parametrize("product_id", ["test-spotlight"])
def test_product_constraints_response(
product_id: str,
Expand Down Expand Up @@ -83,6 +100,11 @@ def test_get_products_pagination(
"rel": "self",
"type": "application/json",
},
{
"href": f"http://stapiserver/products/{product_id}/conformance",
"rel": "conformance",
"type": "application/json",
},
{
"href": f"http://stapiserver/products/{product_id}/constraints",
"rel": "constraints",
Expand Down