Repository: stac-utils/stac-fastapi
Pull request #701 (2024-05-31 13:06:07)

set default value for Query attribute for `QueryExtensionPostRequest` model
#700 


Patch:
diff --git a/CHANGES.md b/CHANGES.md
index 46d284f..0229dcf 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,6 +2,12 @@
 
 ## [Unreleased] - TBD
 
+## [3.0.0a2] - 2024-05-31
+
+### Fixed
+
+* Fix missing default (`None`) for optional `query` attribute in `QueryExtensionPostRequest` model ([#701](https://github.com/stac-utils/stac-fastapi/pull/701))
+
 ## [3.0.0a1] - 2024-05-22
 
 ### Changed
diff --git a/stac_fastapi/extensions/stac_fastapi/extensions/core/query/request.py b/stac_fastapi/extensions/stac_fastapi/extensions/core/query/request.py
index 8b28288..7f8425e 100644
--- a/stac_fastapi/extensions/stac_fastapi/extensions/core/query/request.py
+++ b/stac_fastapi/extensions/stac_fastapi/extensions/core/query/request.py
@@ -18,4 +18,4 @@ class QueryExtensionGetRequest(APIRequest):
 class QueryExtensionPostRequest(BaseModel):
     """Query Extension POST request model."""
 
-    query: Optional[Dict[str, Dict[str, Any]]]
+    query: Optional[Dict[str, Dict[str, Any]]] = None


Test patch:
diff --git a/stac_fastapi/extensions/tests/test_query.py b/stac_fastapi/extensions/tests/test_query.py
new file mode 100644
index 0000000..7674547
--- /dev/null
+++ b/stac_fastapi/extensions/tests/test_query.py
@@ -0,0 +1,95 @@
+import json
+from typing import Iterator
+from urllib.parse import quote_plus, unquote_plus
+
+import pytest
+from starlette.testclient import TestClient
+
+from stac_fastapi.api.app import StacApi
+from stac_fastapi.api.models import create_get_request_model, create_post_request_model
+from stac_fastapi.extensions.core import QueryExtension
+from stac_fastapi.types.config import ApiSettings
+from stac_fastapi.types.core import BaseCoreClient
+
+
+class DummyCoreClient(BaseCoreClient):
+    def all_collections(self, *args, **kwargs):
+        raise NotImplementedError
+
+    def get_collection(self, *args, **kwargs):
+        raise NotImplementedError
+
+    def get_item(self, *args, **kwargs):
+        raise NotImplementedError
+
+    def get_search(self, *args, **kwargs):
+        return kwargs.pop("query", None)
+
+    def post_search(self, *args, **kwargs):
+        return args[0].query
+
+    def item_collection(self, *args, **kwargs):
+        raise NotImplementedError
+
+
+@pytest.fixture
+def client() -> Iterator[TestClient]:
+    settings = ApiSettings()
+    extensions = [QueryExtension()]
+
+    api = StacApi(
+        settings=settings,
+        client=DummyCoreClient(),
+        extensions=extensions,
+        search_get_request_model=create_get_request_model(extensions),
+        search_post_request_model=create_post_request_model(extensions),
+    )
+    with TestClient(api.app) as client:
+        yield client
+
+
+def test_search_query_get(client: TestClient):
+    """Test search GET endpoints with query ext."""
+    response = client.get(
+        "/search",
+        params={"collections": ["test"]},
+    )
+    assert response.is_success
+    assert not response.text
+
+    response = client.get(
+        "/search",
+        params={
+            "collections": ["test"],
+            "query": quote_plus(
+                json.dumps({"eo:cloud_cover": {"gte": 95}}),
+            ),
+        },
+    )
+    assert response.is_success, response.json()
+    query = json.loads(unquote_plus(response.json()))
+    assert query["eo:cloud_cover"] == {"gte": 95}
+
+
+def test_search_query_post(client: TestClient):
+    """Test search POST endpoints with query ext."""
+    response = client.post(
+        "/search",
+        json={
+            "collections": ["test"],
+        },
+    )
+
+    assert response.is_success
+    assert not response.text
+
+    response = client.post(
+        "/search",
+        json={
+            "collections": ["test"],
+            "query": {"eo:cloud_cover": {"gte": 95}},
+        },
+    )
+
+    assert response.is_success, response.json()
+    assert response.json()["eo:cloud_cover"] == {"gte": 95}