Skip to main content
Glama
test_airports.py10.4 kB
"""Tests for airport resolution functionality.""" from unittest.mock import patch import pytest from aerospace_mcp.core import ( AirportResolutionError, _airport_from_iata, _find_city_airports, _resolve_endpoint, ) class TestAirportFromIata: """Tests for _airport_from_iata function.""" @pytest.mark.unit def test_valid_iata_code(self, mock_airports_iata, sjc_airport): """Test resolving a valid IATA code.""" result = _airport_from_iata("SJC") assert result is not None assert result.iata == "SJC" assert result.icao == "KSJC" assert result.name == "San Jose International Airport" assert result.city == "San Jose" assert result.country == "US" assert result.lat == 37.3626 assert result.lon == -121.929 assert result.tz == "America/Los_Angeles" @pytest.mark.unit def test_case_insensitive_iata(self, mock_airports_iata): """Test that IATA codes are case insensitive.""" result_lower = _airport_from_iata("sjc") result_upper = _airport_from_iata("SJC") result_mixed = _airport_from_iata("sJc") assert result_lower is not None assert result_upper is not None assert result_mixed is not None assert result_lower.iata == result_upper.iata == result_mixed.iata == "SJC" @pytest.mark.unit def test_invalid_iata_code(self, mock_airports_iata): """Test resolving an invalid IATA code.""" result = _airport_from_iata("INVALID") assert result is None @pytest.mark.unit def test_empty_iata_code(self, mock_airports_iata): """Test resolving an empty IATA code.""" result = _airport_from_iata("") assert result is None @pytest.mark.unit @pytest.mark.parametrize( "iata,expected_iata,should_exist", [ ("SJC", "SJC", True), ("NRT", "NRT", True), ("INVALID", None, False), ("", None, False), ("XYZ", None, False), ], ) def test_airport_from_iata_parametrized( self, mock_airports_iata, iata, expected_iata, should_exist ): """Parametrized test for various IATA codes.""" result = _airport_from_iata(iata) if should_exist: assert result is not None assert result.iata == expected_iata else: assert result is None class TestFindCityAirports: """Tests for _find_city_airports function.""" @pytest.mark.unit def test_san_jose_us(self, mock_airports_iata): """Test finding airports for San Jose, US.""" results = _find_city_airports("San Jose", "US") assert len(results) == 1 assert results[0].iata == "SJC" assert results[0].city == "San Jose" assert results[0].country == "US" @pytest.mark.unit def test_case_insensitive_city_search(self, mock_airports_iata): """Test that city search is case insensitive.""" results_lower = _find_city_airports("san jose", "US") results_upper = _find_city_airports("SAN JOSE", "US") results_mixed = _find_city_airports("San Jose", "US") assert len(results_lower) == len(results_upper) == len(results_mixed) == 1 assert results_lower[0].iata == results_upper[0].iata == results_mixed[0].iata @pytest.mark.unit def test_city_without_country(self, mock_airports_iata): """Test finding airports for a city without specifying country.""" results = _find_city_airports("San Jose") assert len(results) >= 1 assert any(airport.iata == "SJC" for airport in results) @pytest.mark.unit def test_international_airport_preference(self, mock_airports_iata): """Test that international airports are preferred in sorting.""" # Add another airport for the same city to test sorting with patch( "aerospace_mcp.core._AIRPORTS_IATA", { **mock_airports_iata, "SJC": { "iata": "SJC", "icao": "KSJC", "name": "San Jose International Airport", "city": "San Jose", "country": "US", "lat": 37.3626, "lon": -121.929, }, "SJO": { "iata": "SJO", "icao": "MROC", "name": "Juan Santamaría Airport", "city": "San Jose", "country": "CR", "lat": 9.9936, "lon": -84.2081, }, }, ): results = _find_city_airports("San Jose") # International airports should come first international_airports = [ a for a in results if "international" in a.name.lower() ] if international_airports: assert results[0] in international_airports @pytest.mark.unit def test_nonexistent_city(self, mock_airports_iata): """Test searching for a non-existent city.""" results = _find_city_airports("NonexistentCity", "US") assert len(results) == 0 @pytest.mark.unit def test_empty_city_name(self, mock_airports_iata): """Test searching with empty city name.""" results = _find_city_airports("", "US") assert len(results) == 0 @pytest.mark.unit def test_country_filtering(self, mock_airports_iata): """Test that country filtering works correctly.""" results_us = _find_city_airports("San Jose", "US") results_cr = _find_city_airports("San Jose", "CR") # Should only get US airports for airport in results_us: assert airport.country == "US" # Should only get CR airports (none in our test data) assert len(results_cr) == 0 @pytest.mark.unit @pytest.mark.parametrize( "city,country,expected_iatas", [ ("San Jose", "US", ["SJC"]), ("San Jose", None, ["SJC"]), ("Tokyo", "JP", ["NRT"]), ("NonexistentCity", "US", []), ("", "US", []), ], ) def test_find_city_airports_parametrized( self, mock_airports_iata, city, country, expected_iatas ): """Parametrized test for city airport search.""" results = _find_city_airports(city, country) result_iatas = [airport.iata for airport in results] assert result_iatas == expected_iatas class TestResolveEndpoint: """Tests for _resolve_endpoint function.""" @pytest.mark.unit def test_resolve_with_preferred_iata(self, mock_airports_iata): """Test resolving with a preferred IATA code.""" result = _resolve_endpoint( city="Any City", country=None, prefer_iata="SJC", role="departure" ) assert result.iata == "SJC" assert result.city == "San Jose" @pytest.mark.unit def test_resolve_with_invalid_preferred_iata(self, mock_airports_iata): """Test resolving with an invalid preferred IATA code.""" with pytest.raises( AirportResolutionError, match="departure: IATA 'INVALID' not found" ): _resolve_endpoint( city="Any City", country=None, prefer_iata="INVALID", role="departure" ) @pytest.mark.unit def test_resolve_by_city(self, mock_airports_iata): """Test resolving by city name.""" result = _resolve_endpoint( city="San Jose", country="US", prefer_iata=None, role="departure" ) assert result.iata == "SJC" assert result.city == "San Jose" @pytest.mark.unit def test_resolve_nonexistent_city(self, mock_airports_iata): """Test resolving a non-existent city.""" with pytest.raises( AirportResolutionError, match="departure: no airport for city='NonexistentCity'", ): _resolve_endpoint( city="NonexistentCity", country="US", prefer_iata=None, role="departure" ) @pytest.mark.unit def test_resolve_with_role_in_error_message(self, mock_airports_iata): """Test that the role is included in error messages.""" with pytest.raises( AirportResolutionError, match="arrival: IATA 'INVALID' not found" ): _resolve_endpoint( city="Any City", country=None, prefer_iata="INVALID", role="arrival" ) @pytest.mark.unit def test_resolve_prefers_iata_over_city(self, mock_airports_iata): """Test that preferred IATA takes precedence over city.""" result = _resolve_endpoint( city="Tokyo", # Would normally resolve to NRT country="JP", prefer_iata="SJC", # But we prefer SJC role="departure", ) assert result.iata == "SJC" assert result.city == "San Jose" # Not Tokyo class TestAirportResolutionIntegration: """Integration tests for airport resolution.""" @pytest.mark.integration def test_real_airport_data_sjc(self): """Test with real airport data - SJC should exist.""" result = _airport_from_iata("SJC") if result: # Only test if real data is available assert result.iata == "SJC" assert result.country == "US" assert "San Jose" in result.name or "San Jose" in result.city @pytest.mark.integration def test_real_airport_data_city_search(self): """Test city search with real airport data.""" results = _find_city_airports("San Jose", "US") if results: # Only test if real data is available # Should find at least one airport assert len(results) > 0 # At least one should be SJC iatas = [airport.iata for airport in results] assert "SJC" in iatas @pytest.mark.integration def test_error_handling_with_real_data(self): """Test error handling with real airport data.""" # This should always fail regardless of real data result = _airport_from_iata("DEFINITELYNOTREAL123") assert result is None results = _find_city_airports("DefinitelyNotARealCity123", "XX") assert len(results) == 0

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cheesejaguar/aerospace-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server