Skip to content

Commit

Permalink
Check if extension is passed via query parameter; update unit tests a…
Browse files Browse the repository at this point in the history
…ccordingly
  • Loading branch information
feba-rajan committed Aug 8, 2024
1 parent a2286da commit 5ce9a95
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 16 deletions.
23 changes: 8 additions & 15 deletions application/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,14 @@ class DigitalLandJSONResponse(Response):
media_type = "application/json"

def render(self, content: typing.Any) -> bytes:
try:
if isinstance(content, dict):
return json.dumps(
content,
ensure_ascii=False,
allow_nan=False,
indent=None,
separators=(",", ":"),
cls=NoneToEmptyStringEncoder,
).encode("utf-8")
else:
raise TypeError("Content must be a dictionary")
except Exception as e:
logger.error(f"Error rendering content: {e}")
raise
return json.dumps(
content,
ensure_ascii=False,
allow_nan=False,
indent=None,
separators=(",", ":"),
cls=NoneToEmptyStringEncoder,
).encode("utf-8")


def make_links(scheme, netloc, path, query, data):
Expand Down
89 changes: 88 additions & 1 deletion application/routers/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ def search_entities(
extension: Optional[SuffixEntity] = None,
session: Session = Depends(get_session),
):
# Determine if we should use the query parameter or the path parameter extension
if request.query_params.get("extension"):
extension = None
else:
extension = extension

# get query_filters as a dict
query_params = asdict(query_filters)
# TODO minimse queries by using normal queries below rather than returning the names
Expand All @@ -262,7 +268,6 @@ def search_entities(
validate_typologies(query_params.get("typology", None), typology_names)
# Run entity query
data = get_entity_search(session, query_params)

# the query does some normalisation to remove empty
# params and they get returned from search
params = data["params"]
Expand Down Expand Up @@ -338,6 +343,87 @@ def search_entities(
)


# def search_entities_no_extension(
# request: Request,
# query_filters: QueryFilters = Depends(),
# session: Session = Depends(get_session),
# ):
# print("hello no extension")
# # get query_filters as a dict
# query_params = asdict(query_filters)
# # TODO minimse queries by using normal queries below rather than returning the names
# # queries required for additional validations
# dataset_names = get_dataset_names(session)
# typology_names = get_typology_names(session)

# # additional validations
# validate_dataset(query_params.get("dataset", None), dataset_names)
# validate_typologies(query_params.get("typology", None), typology_names)
# # Run entity query
# print("params", query_params)
# data = get_entity_search(session, query_params)
# # the query does some normalisation to remove empty
# # params and they get returned from search
# params = data["params"]
# scheme = request.url.scheme
# netloc = request.url.netloc
# path = request.url.path
# query = request.url.query
# links = make_links(scheme, netloc, path, query, data)

# typologies = get_typologies_with_entities(session)
# typologies = [t.dict() for t in typologies]
# # dataset facet
# response = get_datasets(session)
# columns = ["dataset", "name", "plural", "typology", "themes", "paint_options"]
# datasets = [dataset.dict(include=set(columns)) for dataset in response]

# local_authorities = get_local_authorities(session, "local-authority")
# local_authorities = [la.dict() for la in local_authorities]

# if links.get("prev") is not None:
# prev_url = links["prev"]
# else:
# prev_url = None

# if links.get("next") is not None:
# next_url = links["next"]
# else:
# next_url = None
# # default is HTML
# has_geographies = any((e.typology == "geography" for e in data["entities"]))
# return templates.TemplateResponse(
# "search.html",
# {
# "request": request,
# "count": data["count"],
# "limit": params["limit"],
# "data": data["entities"],
# "datasets": datasets,
# "local_authorities": local_authorities,
# "typologies": typologies,
# "query": {"params": params},
# "active_filters": [
# filter_name
# for filter_name, values in params.items()
# if filter_name != "limit" and values is not None
# ],
# "url_query_params": {
# "str": ("&").join(
# [
# "{}={}".format(param[0], param[1])
# for param in request.query_params._list
# ]
# ),
# "list": request.query_params._list,
# },
# "next_url": next_url,
# "prev_url": prev_url,
# "has_geographies": has_geographies,
# },
# )


# Route ordering in important. Match routes with extensions first
router.add_api_route(
".{extension}",
Expand All @@ -348,6 +434,7 @@ def search_entities(
)
router.add_api_route(
"/",
# endpoint=search_entities_no_extension,
endpoint=search_entities,
responses={
200: {
Expand Down
52 changes: 52 additions & 0 deletions tests/unit/routers/test_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,9 @@ def test_search_entities_no_entities_returned_no_query_params_json(mocker):
mocker.patch(
"application.routers.entity.get_typology_names", return_value=["geography"]
)

request = MagicMock()
request.query_params.get.return_value = None
extension = MagicMock()
extension.value = "json"
result = search_entities(
Expand Down Expand Up @@ -520,6 +522,7 @@ def test_search_entities_no_entities_returned_no_query_params_geojson(mocker):
"application.routers.entity.get_typology_names", return_value=["geography"]
)
request = MagicMock()
request.query_params.get.return_value = None
extension = MagicMock()
extension.value = "geojson"
result = search_entities(
Expand Down Expand Up @@ -608,6 +611,7 @@ def test_search_entities_multiple_entities_returned_no_query_params_json(
"application.routers.entity.get_typology_names", return_value=["geography"]
)
request = MagicMock()
request.query_params.get.return_value = None
extension = MagicMock()
extension.value = "json"
result = search_entities(
Expand Down Expand Up @@ -642,6 +646,7 @@ def test_search_entities_multiple_entities_returned_no_query_params_geojson(
"application.routers.entity.get_typology_names", return_value=["geography"]
)
request = MagicMock()
request.query_params.get.return_value = None
extension = MagicMock()
extension.value = "geojson"
result = search_entities(
Expand All @@ -655,3 +660,50 @@ def test_search_entities_multiple_entities_returned_no_query_params_geojson(
assert "type" in result, "expecting geojson structure to have type attribute"
assert result["type"] == "FeatureCollection"
assert "features" in result, "expected features attribute"


@pytest.mark.parametrize("extension_value", [("json"), ("geojson"), (None)])
def test_search_entities_with_query_extension(
mocker, extension_value, multiple_entity_models
):
request = MagicMock()
request.query_params.get.return_value = extension_value
extension = MagicMock()
extension.value = extension_value

normalised_query_params = normalised_params(asdict(QueryFilters()))
mocker.patch(
"application.routers.entity.get_entity_search",
return_value={
"params": normalised_query_params,
"count": 0,
"entities": multiple_entity_models,
},
)
mocker.patch(
"application.routers.entity.get_dataset_names",
return_value=["dataset1"],
)
mocker.patch(
"application.routers.entity.get_typology_names",
return_value=["typology1"],
)
mock_get_session = mocker.patch(
"application.routers.entity.get_session", return_value=MagicMock()
)

result = search_entities(
request=request,
query_filters=QueryFilters(),
extension=extension,
session=mock_get_session.return_value,
)
try:
result.template.render(result.context)
assert True
except Exception:
if hasattr(result, "context"):
logging.warning(f"context:{result.context}")
else:
logging.warning("result has no context")
assert False, "template unable to render, missing variable(s) from context"

0 comments on commit 5ce9a95

Please sign in to comment.