""" Govmap API health check tests. These tests verify the Govmap API is working and hasn't changed significantly. Run periodically (e.g., weekly) with: pytest -m api_health IMPORTANT: These make real API calls and take longer to run. """ import pytest from nadlan_mcp.govmap import GovmapClient from nadlan_mcp.govmap.models import AutocompleteResponse, Deal @pytest.fixture def client(): """Create a real Govmap client (no mocking).""" return GovmapClient() class TestAutocompleteAPIHealth: """Test autocomplete API endpoint health.""" @pytest.mark.api_health def test_autocomplete_returns_results(self, client): """Verify autocomplete returns results for known address.""" response = client.autocomplete_address("סוקולוב 38 חולון") assert isinstance(response, AutocompleteResponse) assert response.results_count > 0 assert len(response.results) > 0 assert response.results[0].text is not None @pytest.mark.api_health def test_autocomplete_response_structure(self, client): """Verify autocomplete response has expected structure.""" response = client.autocomplete_address("דיזנגוף תל אביב") # Check response model fields exist assert hasattr(response, "results_count") assert hasattr(response, "results") # Check result fields if len(response.results) > 0: result = response.results[0] assert hasattr(result, "id") assert hasattr(result, "text") assert hasattr(result, "type") assert hasattr(result, "coordinates") @pytest.mark.api_health def test_autocomplete_coordinates_present(self, client): """Verify autocomplete returns coordinates for addresses.""" response = client.autocomplete_address("רוטשילד 1 תל אביב") assert len(response.results) > 0 # At least one result should have coordinates has_coordinates = any(r.coordinates is not None for r in response.results) assert has_coordinates, "No results have coordinates" class TestDealsAPIHealth: """Test deals API endpoints health.""" @pytest.mark.api_health def test_get_deals_by_radius_works(self, client): """Verify get_deals_by_radius returns data.""" # Use known working coordinates from E2E tests (Holon area) # client.get_deals_by_radius expects (lon, lat) tuple in ITM format lon, lat = 3870928.84, 3766290.19 polygons = client.get_deals_by_radius((lon, lat), radius=100) # Should return some polygon data assert isinstance(polygons, list) assert len(polygons) > 0 @pytest.mark.api_health def test_get_street_deals_works(self, client): """Verify get_street_deals returns deals.""" # First get a polygon ID from autocomplete response = client.autocomplete_address("סוקולוב 38 חולון") assert len(response.results) > 0 coords = response.results[0].coordinates assert coords is not None, "Address has no coordinates" # Get polygons near this address polygons = client.get_deals_by_radius((coords.longitude, coords.latitude), radius=50) assert len(polygons) > 0, "No polygons found" # Get street deals for first polygon polygon_id = polygons[0].get("polygon_id") assert polygon_id is not None, "Polygon has no ID" deals = client.get_street_deals(polygon_id, limit=10) # Verify deals structure assert isinstance(deals, list) if len(deals) > 0: deal = deals[0] assert isinstance(deal, Deal) assert deal.objectid is not None assert deal.deal_amount is not None @pytest.mark.api_health def test_deal_model_fields_present(self, client): """Verify Deal model has expected fields.""" # Get some real deals response = client.autocomplete_address("דיזנגוף 50 תל אביב") if len(response.results) == 0: pytest.skip("No autocomplete results") coords = response.results[0].coordinates if coords is None: pytest.skip("No coordinates") polygons = client.get_deals_by_radius((coords.longitude, coords.latitude), radius=50) if len(polygons) == 0: pytest.skip("No polygons") polygon_id = polygons[0].get("polygon_id") deals = client.get_street_deals(polygon_id, limit=5) if len(deals) == 0: pytest.skip("No deals found") deal = deals[0] # Check required fields assert hasattr(deal, "objectid") assert hasattr(deal, "deal_amount") assert hasattr(deal, "deal_date") # Check common optional fields assert hasattr(deal, "asset_area") assert hasattr(deal, "property_type_description") assert hasattr(deal, "rooms") assert hasattr(deal, "floor") # Check computed field assert hasattr(deal, "price_per_sqm") class TestAPIDataQuality: """Test data quality from API.""" @pytest.mark.api_health def test_deal_amounts_reasonable(self, client): """Verify deal amounts are in reasonable range.""" response = client.autocomplete_address("חולון") if len(response.results) == 0: pytest.skip("No results") coords = response.results[0].coordinates if coords is None: pytest.skip("No coordinates") polygons = client.get_deals_by_radius((coords.longitude, coords.latitude), radius=100) if len(polygons) == 0: pytest.skip("No polygons") polygon_id = polygons[0].get("polygon_id") deals = client.get_street_deals(polygon_id, limit=20) if len(deals) == 0: pytest.skip("No deals") # Check deal amounts are reasonable (10K to 100M NIS) for deal in deals: if deal.deal_amount > 0: assert ( 10000 <= deal.deal_amount <= 100000000 ), f"Deal amount {deal.deal_amount} outside reasonable range" @pytest.mark.api_health def test_dates_are_recent(self, client): """Verify deals have recent dates.""" from datetime import date, timedelta response = client.autocomplete_address("תל אביב") if len(response.results) == 0: pytest.skip("No results") coords = response.results[0].coordinates if coords is None: pytest.skip("No coordinates") polygons = client.get_deals_by_radius((coords.longitude, coords.latitude), radius=100) if len(polygons) == 0: pytest.skip("No polygons") polygon_id = polygons[0].get("polygon_id") deals = client.get_street_deals(polygon_id, limit=50) if len(deals) == 0: pytest.skip("No deals") # At least some deals should be from last 5 years cutoff = date.today() - timedelta(days=5 * 365) recent_deals = [d for d in deals if isinstance(d.deal_date, date) and d.deal_date >= cutoff] assert len(recent_deals) > 0, "No recent deals found (within last 5 years)" class TestAPIIntegration: """Test full integration workflows.""" @pytest.mark.api_health def test_full_address_to_deals_workflow(self, client): """Test complete workflow: address -> coordinates -> polygons -> deals.""" # Step 1: Autocomplete response = client.autocomplete_address("רוטשילד 1 תל אביב") assert len(response.results) > 0, "Autocomplete failed" # Step 2: Get coordinates coords = response.results[0].coordinates assert coords is not None, "No coordinates returned" # Step 3: Get polygons polygons = client.get_deals_by_radius((coords.longitude, coords.latitude), radius=50) assert len(polygons) > 0, "No polygons found" # Step 4: Get deals polygon_id = polygons[0].get("polygon_id") deals = client.get_street_deals(polygon_id, limit=10) # Should complete without errors assert isinstance(deals, list), "Deals should be a list" @pytest.mark.api_health def test_api_response_times_reasonable(self, client): """Verify API responds within reasonable time.""" import time # Test autocomplete response time start = time.time() client.autocomplete_address("תל אביב") autocomplete_time = time.time() - start assert autocomplete_time < 5.0, f"Autocomplete took {autocomplete_time:.2f}s (too slow)" # Test deals query response time response = client.autocomplete_address("חולון") if len(response.results) > 0 and response.results[0].coordinates: coords = response.results[0].coordinates start = time.time() client.get_deals_by_radius((coords.longitude, coords.latitude), radius=50) deals_time = time.time() - start assert deals_time < 10.0, f"Deals query took {deals_time:.2f}s (too slow)"