Skip to content

Commit a9a0035

Browse files
committed
Add pytest test_pagination_different_collections
1 parent 8874baa commit a9a0035

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed

tests/resources/test_item.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,3 +1794,118 @@ async def test_item_asset_change(app_client, load_test_data):
17941794
# We get "𒍟※" because PgSTAC set it when ingesting (`description`is item-assets)
17951795
# because we removed item-assets, pgstac cannot hydrate this field, and thus return "𒍟※"
17961796
assert resp.json()["features"][0]["assets"]["qa_pixel"]["description"] == "𒍟※"
1797+
1798+
@pytest.mark.parametrize("usecase", ("ok1", "ok2", "ko"))
1799+
async def test_pagination_different_collections(app_client, load_test_data, usecase):
1800+
"""
1801+
This test demonstrates an error case ("ko" use case): when the same item exists in two collections, the
1802+
/search endpoint without 'limit' parameter returns the expected result = all items from all collections.
1803+
But when we add a 'limit' parameter, the /search endpoint fails: it returns only items from the first collection,
1804+
with a 'next' link that should allow to get items from the next collections, but this 'next' link doesn't work:
1805+
it returns nothing.
1806+
1807+
This test also implements two nominal use cases that work as expected ("ok1" and "ok2"): when two different items
1808+
exist in the same collection, and when two different items exist in two different collections.
1809+
"""
1810+
1811+
col1_data = load_test_data("test_collection.json")
1812+
col2_data = load_test_data("test2_collection.json")
1813+
1814+
item1_data = load_test_data("test_item.json")
1815+
item2_data = load_test_data("test_item2.json")
1816+
1817+
# KO use case: the same item exists in two different collections
1818+
if usecase == "ko":
1819+
assert (await app_client.post("/collections", json=col1_data)).status_code == 201
1820+
assert (await app_client.post("/collections", json=col2_data)).status_code == 201
1821+
1822+
for col_data in col1_data, col2_data:
1823+
item1_data["collection"] = col_data["id"]
1824+
assert (await app_client.post(f"/collections/{col_data['id']}/items", json=item1_data)).status_code == 201
1825+
1826+
# First OK use case: two different items in the same collection
1827+
elif usecase == "ok1":
1828+
assert (await app_client.post("/collections", json=col1_data)).status_code == 201
1829+
1830+
for item_data in item1_data, item2_data:
1831+
item_data["collection"] = col1_data["id"]
1832+
assert (await app_client.post(f"/collections/{col1_data['id']}/items", json=item_data)).status_code == 201
1833+
1834+
# Second OK use case: two different items in two different collections
1835+
elif usecase == "ok2":
1836+
assert (await app_client.post("/collections", json=col1_data)).status_code == 201
1837+
assert (await app_client.post("/collections", json=col2_data)).status_code == 201
1838+
1839+
item1_data["collection"] = col1_data["id"]
1840+
assert (await app_client.post(f"/collections/{col1_data['id']}/items", json=item1_data)).status_code == 201
1841+
1842+
item2_data["collection"] = col2_data["id"]
1843+
assert (await app_client.post(f"/collections/{col2_data['id']}/items", json=item2_data)).status_code == 201
1844+
1845+
# Call the /search endpoint without parameters.
1846+
# The result is always as expected in all use cases: two features are returned.
1847+
resp = await app_client.get("/search")
1848+
assert resp.status_code == 200
1849+
contents = resp.json()
1850+
assert contents["numberReturned"] == 2
1851+
all_features = contents["features"] # save returned features
1852+
1853+
# Call the /search endpoint again, but this time return only one feature per page
1854+
resp = await app_client.get("/search", params={"limit": 1})
1855+
contents = None
1856+
1857+
# Loop on all pages/features. For each page, we will:
1858+
# - check the returned feature contents
1859+
# - check the previous link contents, if any
1860+
# - get the next feature
1861+
for page, expected_feature in enumerate(all_features):
1862+
page += 1
1863+
is_first_page = (page == 1)
1864+
is_last_page = (page == len(all_features))
1865+
1866+
# Get returned feature contents, save old feature contents
1867+
previous_contents = contents
1868+
assert resp.status_code == 200
1869+
contents = resp.json()
1870+
1871+
# Get the previous and next links
1872+
links = contents["links"]
1873+
previous_urls = [link["href"] for link in links if link["rel"] == "previous"]
1874+
next_urls = [link["href"] for link in links if link["rel"] == "next"]
1875+
1876+
# Check that they are present, except for:
1877+
# - the first page has no previous link
1878+
# - the last page has no next link
1879+
if is_first_page:
1880+
assert len(previous_urls) == 0
1881+
previous_url = None
1882+
else:
1883+
assert len(previous_urls) == 1
1884+
previous_url = previous_urls[0]
1885+
1886+
if is_last_page:
1887+
assert len(next_urls) == 0
1888+
next_url = None
1889+
else:
1890+
assert len(next_urls) == 1
1891+
next_url = next_urls[0]
1892+
1893+
print(f"""
1894+
page: {page}
1895+
previous url: {previous_url}
1896+
next url: {next_url}
1897+
numberReturned: {contents['numberReturned']}""")
1898+
1899+
# A single feature should always be returned. Check its contents.
1900+
assert contents["numberReturned"] == 1
1901+
feature = contents["features"][0]
1902+
print(f"returned feature: {feature['collection']}:{feature['id']}")
1903+
assert expected_feature == feature
1904+
1905+
# Check the previous link contents
1906+
if not is_first_page:
1907+
assert previous_contents == (await app_client.get(previous_url)).json()
1908+
1909+
# Get the next feature
1910+
if not is_last_page:
1911+
resp = await app_client.get(next_url)

0 commit comments

Comments
 (0)