def test_stac_collections(stac_client: FlaskClient): response = get_json(stac_client, "/stac") assert response[ "id"] == "odc-explorer", "Expected default unconfigured endpoint id" assert (response["title"] == "Default ODC Explorer instance" ), "Expected default unconfigured endpoint title" # A child link to each "collection" (product) child_links = [l for l in response["links"] if l["rel"] == "child"] other_links = [l for l in response["links"] if l["rel"] != "child"] # a "self" link. assert len(other_links) == 1 assert other_links[0]["rel"] == "self" found_products = set() for child_link in child_links: product_name = child_link["title"] href = child_link["href"] print(f"Loading collection page for {product_name}: {repr(href)}") collection_data = get_json(stac_client, href) assert collection_data["id"] == product_name # TODO: assert items, properties, etc. found_products.add(product_name) # We should have seen all products in the index expected_products = set(dt.name for dt in _model.STORE.all_dataset_types()) assert found_products == expected_products
def expect_404(url: str, message_contains: str = None): __tracebackhide__ = True data = get_json(stac_client, url, expect_status_code=404) if message_contains and message_contains not in data.get("description", ""): raise AssertionError( f"Expected {message_contains!r} in description of response {data!r}" )
def get_item(client: FlaskClient, url: str) -> Dict: """ Get a URL, expecting a single valid Stac Item to be there """ with DebugContext(f"Requested {repr(url)}"): data = get_json(client, url) validate_item(data) return data
def get_collection(client: FlaskClient, url: str, validate=True) -> Dict: """ Get a URL, expecting a valid stac collection document to be there""" with DebugContext(f"Requested {repr(url)}"): data = get_json(client, url) if validate: assert_collection(data) return data
def test_stac_collections(stac_client: FlaskClient): response = get_json(stac_client, "/stac") _CATALOG_SCHEMA.validate(response) assert response["id"] == "odc-explorer", "Expected default unconfigured endpoint id" assert ( response["title"] == "Default ODC Explorer instance" ), "Expected default unconfigured endpoint title" # A child link to each "collection" (product) child_links = [r for r in response["links"] if r["rel"] == "child"] other_links = [r for r in response["links"] if r["rel"] != "child"] assert other_links == [ { "description": "All product collections", "href": "http://localhost/stac/collections", "rel": "children", "title": "Collections", "type": "application/json", }, { "href": "http://localhost/stac/search", "rel": "search", "title": "Item Search", "type": "application/json", }, {"href": "http://localhost/stac", "rel": "self"}, {"href": "http://localhost/stac", "rel": "root"}, ] # All expected products and their dataset counts. expected_product_counts = { dt.name: _model.STORE.index.datasets.count(product=dt.name) for dt in _model.STORE.all_dataset_types() } found_collection_ids = set() for child_link in child_links: product_name: str = child_link["title"] href: str = child_link["href"] print(f"Loading collection page for {product_name}: {repr(href)}") collection_data = get_collection(stac_client, href, validate=True) assert collection_data["id"] == product_name # TODO: assert items, properties, etc. found_collection_ids.add(product_name) virtual_collections = ("Arrivals",) # We should have seen all products in the index assert sorted(found_collection_ids) == sorted( virtual_collections + tuple(expected_product_counts.keys()) )
def test_stac_collection_items(stac_client: FlaskClient): """ Follow the links to the "high_tide_comp_20p" collection and ensure it includes all of our tests data. """ collections = get_json(stac_client, "/stac") for link in collections["links"]: if link["rel"] == "child" and link["title"] == "high_tide_comp_20p": collection_href = link["href"] break else: assert False, "high_tide_comp_20p not found in collection list" scene_collection = get_json(stac_client, collection_href) pprint(scene_collection) assert scene_collection == { "stac_version": "0.6.0", "id": "high_tide_comp_20p", "title": "high_tide_comp_20p", "properties": {}, "description": "High Tide 20 percentage composites for entire coastline", "extent": { "spatial": [ 112.223_058_990_767_51, -43.829_196_553_065_4, 153.985_054_424_922_77, -10.237_104_814_250_783, ], "temporal": ["2008-06-01T00:00:00+00:00", "2008-06-01T00:00:00+00:00"], }, "links": [{ "href": "http://localhost/collections/high_tide_comp_20p/items", "rel": "items", }], "providers": [], }
def test_huge_page_request(stac_client: FlaskClient): """Return an error if they try to request beyond max-page-size limit""" error_message_json = get_json( stac_client, f"/stac/search?&limit={OUR_DATASET_LIMIT+1}", expect_status_code=400, ) assert error_message_json == { "code": 400, "name": "Bad Request", "description": f"Max page size is {OUR_DATASET_LIMIT}. Use the next links instead of a large limit.", }
def test_stac_collection_items(stac_client: FlaskClient): """ Follow the links to the "high_tide_comp_20p" collection and ensure it includes all of our tests data. """ collections = get_json(stac_client, "/stac") for link in collections["links"]: if link["rel"] == "child" and link["title"] == "high_tide_comp_20p": collection_href = link["href"] break else: raise AssertionError("high_tide_comp_20p not found in collection list") scene_collection = get_collection(stac_client, collection_href, validate=False) assert scene_collection == { "stac_version": "1.0.0", "type": "Collection", "id": "high_tide_comp_20p", "title": "high_tide_comp_20p", "license": "CC-BY-4.0", "properties": {}, "description": "High Tide 20 percentage composites for entire coastline", "extent": { "spatial": { "bbox": [ [ 112.223_058_990_767_51, -43.829_196_553_065_4, 153.985_054_424_922_77, -10.237_104_814_250_783, ] ] }, "temporal": { "interval": [["2008-06-01T00:00:00+00:00", "2008-06-01T00:00:00+00:00"]] }, }, "links": [ { "href": stac_url("collections/high_tide_comp_20p/items"), "rel": "items", }, { "rel": "root", "href": "http://localhost/stac", }, ], "providers": [], }
def get_item(client: FlaskClient, url: str) -> Dict: with DebugContext(f"Requested {repr(url)}"): data = get_json(client, url) validate_item(data) return data
def test_stac_search_by_ids(stac_client: FlaskClient, populated_index: Index): def geojson_feature_ids(d: Dict) -> List[str]: return sorted(d.get("id") for d in geojson.get("features", {})) # Can filter to an empty list. Nothing returned. geojson = get_items( stac_client, "/stac/search?&collection=ls7_nbart_albers&ids=", ) assert len(geojson.get("features")) == 0 # Can request one dataset geojson = get_items( stac_client, "/stac/search?ids=cab65f3f-bb38-4605-9d6a-eff5ea786376", ) assert geojson_feature_ids(geojson) == ["cab65f3f-bb38-4605-9d6a-eff5ea786376"] # Other params are ignored when ids is specified (Matching the Stac API spec) geojson = get_items( stac_client, ( "/stac/search?datetime=1975-01-01/1976-01-01&ids=cab65f3f-bb38-4605-9d6a-eff5ea786376" ), ) assert geojson_feature_ids(geojson) == ["cab65f3f-bb38-4605-9d6a-eff5ea786376"] # Can request multiple datasets geojson = get_items( stac_client, ( "/stac/search?&collection=ls7_nbart_albers" "&ids=cab65f3f-bb38-4605-9d6a-eff5ea786376, " "306a5281-02df-4d27-b1eb-b1cda81a35e3," "696c2481-700e-4fec-b438-01396430a688" ), ) assert geojson_feature_ids(geojson) == [ "306a5281-02df-4d27-b1eb-b1cda81a35e3", "696c2481-700e-4fec-b438-01396430a688", "cab65f3f-bb38-4605-9d6a-eff5ea786376", ] assert geojson["numberMatched"] == 3 # Can filter using ids that don't exist. geojson = get_items( stac_client, "/stac/search?&ids=7afd04ad-6080-4ee8-a280-f64853b399ca", ) assert len(geojson.get("features")) == 0 # Old JSON-like syntax should be supported for now. # (Sat-api and the old code used this?) geojson = get_items( stac_client, '/stac/search?ids=["cab65f3f-bb38-4605-9d6a-eff5ea786376"]', ) assert geojson_feature_ids(geojson) == ["cab65f3f-bb38-4605-9d6a-eff5ea786376"] # HTTP-Bad-Request should be returned when not a valid uuid format # TODO: perhaps ideally this should be treated as an unknown id... but this is at # least better than the old Postgres error error_message_json = get_json( stac_client, ("/stac/search?&collection=ls7_nbart_albers" "&ids=7a[-fd04ad[-"), expect_status_code=400, ) assert error_message_json["name"] == "Bad Request"