Spaces:
Running
Running
| """Tests for gazet.search — fuzzy search and ID lookup against real parquet data.""" | |
| import pandas as pd | |
| from gazet.schemas import Place | |
| from gazet.search import ( | |
| get_by_id, | |
| get_division_by_id, | |
| get_natural_earth_by_id, | |
| search_candidates, | |
| search_divisions_area, | |
| search_natural_earth, | |
| ) | |
| class TestSearchDivisionsArea: | |
| def test_returns_dataframe(self, con): | |
| df = search_divisions_area(con, Place(place="India")) | |
| assert isinstance(df, pd.DataFrame) | |
| assert "source" in df.columns | |
| assert "id" in df.columns | |
| def test_matches_known_country(self, con): | |
| df = search_divisions_area(con, Place(place="India")) | |
| assert not df.empty | |
| # At least one result should be India | |
| names = df["name"].str.lower().tolist() | |
| assert any("india" in name for name in names) | |
| def test_limits_results(self, con): | |
| df = search_divisions_area(con, Place(place="a"), limit=3) | |
| assert len(df) <= 3 | |
| def test_empty_result(self, con): | |
| # Extremely unlikely string — Jaro-Winkler always returns top N, | |
| # but similarity should be very low | |
| df = search_divisions_area(con, Place(place="Xyzz98765")) | |
| # Results may still be returned (always top-5) but with low similarity | |
| assert len(df) <= 5 | |
| def test_source_column(self, con): | |
| df = search_divisions_area(con, Place(place="India")) | |
| if not df.empty: | |
| assert (df["source"] == "divisions_area").all() | |
| def test_case_insensitive(self, con): | |
| df_upper = search_divisions_area(con, Place(place="INDIA")) | |
| df_lower = search_divisions_area(con, Place(place="india")) | |
| # Both should return results (even if different similarity scores) | |
| assert not df_upper.empty | |
| assert not df_lower.empty | |
| def test_with_country_filter(self, con): | |
| df = search_divisions_area(con, Place(place="Loja", country="EC")) | |
| # Should find Loja in Ecuador | |
| if not df.empty: | |
| assert "source" in df.columns | |
| def test_similar_names_different_country(self, con): | |
| df = search_divisions_area(con, Place(place="Manchester")) | |
| # Should return results (multiple Manchesters exist) | |
| assert isinstance(df, pd.DataFrame) | |
| def test_include_geometry_flag(self, con): | |
| df = search_divisions_area( | |
| con, Place(place="India"), include_geometry=True, limit=1 | |
| ) | |
| if not df.empty: | |
| assert "geometry" in df.columns | |
| def test_include_bbox_flag(self, con): | |
| df = search_divisions_area( | |
| con, Place(place="India"), include_bbox=True, limit=1 | |
| ) | |
| if not df.empty: | |
| assert "bbox" in df.columns | |
| def test_column_presence(self, con): | |
| df = search_divisions_area(con, Place(place="India"), limit=1) | |
| if not df.empty: | |
| expected_cols = ["source", "id", "name", "country", "subtype", "similarity"] | |
| for col in expected_cols: | |
| assert col in df.columns | |
| class TestSearchNaturalEarth: | |
| def test_returns_dataframe(self, con): | |
| df = search_natural_earth(con, Place(place="Nile")) | |
| assert isinstance(df, pd.DataFrame) | |
| def test_searches_ocean(self, con): | |
| df = search_natural_earth(con, Place(place="Pacific")) | |
| assert isinstance(df, pd.DataFrame) | |
| def test_source_column(self, con): | |
| df = search_natural_earth(con, Place(place="Nile")) | |
| if not df.empty: | |
| assert (df["source"] == "natural_earth").all() | |
| def test_empty_result(self, con): | |
| df = search_natural_earth(con, Place(place="Xyzz98765")) | |
| # Jaro-Winkler always returns top 5, similarity is very low | |
| assert len(df) <= 5 | |
| def test_limits_results(self, con): | |
| df = search_natural_earth(con, Place(place="a"), limit=2) | |
| assert len(df) <= 2 | |
| def test_include_geometry(self, con): | |
| df = search_natural_earth(con, Place(place="Nile"), include_geometry=True) | |
| if not df.empty: | |
| assert "geometry" in df.columns | |
| class TestSearchCandidates: | |
| def test_searches_both_sources(self, con): | |
| results = search_candidates(con, Place(place="India")) | |
| # Should get at least one source | |
| assert len(results) >= 1 | |
| sources = {df["source"].iloc[0] for df in results if not df.empty} | |
| assert "divisions_area" in sources | |
| def test_restricts_to_single_source(self, con): | |
| results = search_candidates( | |
| con, | |
| Place(place="Nile"), | |
| sources=("natural_earth",), | |
| ) | |
| for df in results: | |
| if not df.empty: | |
| assert df["source"].iloc[0] == "natural_earth" | |
| def test_empty_place(self, con): | |
| # Even random strings get fuzzy matches — check results exist | |
| # but have low similarity | |
| results = search_candidates(con, Place(place="Xyzz98765")) | |
| # Results may be non-empty due to fuzzy matching, but similarity low | |
| for df in results: | |
| assert len(df) <= 5 | |
| def test_combine_multiple_places(self, con): | |
| # Search for a place that exists in both sources | |
| results = search_candidates( | |
| con, | |
| Place(place="Brazil"), | |
| sources=("divisions_area", "natural_earth"), | |
| ) | |
| for df in results: | |
| assert isinstance(df, pd.DataFrame) | |
| class TestGetById: | |
| def test_get_division_by_id(self, con): | |
| # First get a valid ID from search | |
| df = search_divisions_area(con, Place(place="India"), limit=1) | |
| if not df.empty: | |
| rid = df["id"].iloc[0] | |
| result = get_division_by_id(con, rid) | |
| assert not result.empty | |
| assert result["id"].iloc[0] == rid | |
| def test_get_natural_earth_by_id(self, con): | |
| df = search_natural_earth(con, Place(place="Nile"), limit=1) | |
| if not df.empty: | |
| rid = df["id"].iloc[0] | |
| result = get_natural_earth_by_id(con, rid) | |
| assert not result.empty | |
| assert result["id"].iloc[0] == rid | |
| def test_get_by_id_auto_infer_divisions(self, con): | |
| df = search_divisions_area(con, Place(place="India"), limit=1) | |
| if not df.empty: | |
| rid = df["id"].iloc[0] | |
| result = get_by_id(con, rid) | |
| assert not result.empty | |
| def test_get_by_id_auto_infer_natural_earth(self, con): | |
| df = search_natural_earth(con, Place(place="Nile"), limit=1) | |
| if not df.empty: | |
| rid = df["id"].iloc[0] | |
| # NE IDs start with "ne_" | |
| assert rid.startswith("ne_") | |
| result = get_by_id(con, rid) | |
| assert not result.empty | |
| def test_get_by_id_invalid(self, con): | |
| result = get_by_id(con, "nonexistent_id_999") | |
| assert result.empty | |
| def test_get_by_id_with_source(self, con): | |
| df = search_divisions_area(con, Place(place="India"), limit=1) | |
| if not df.empty: | |
| rid = df["id"].iloc[0] | |
| result = get_by_id(con, rid, source="divisions_area") | |
| assert not result.empty | |
| assert result["source"].iloc[0] == "divisions_area" | |