8 standalone tests covering Accept-Language header in Nominatim requests and languageCode field in Google Places payload, for both explicit lang values (en, de, fr) and the default fallback (en).
187 lines
6.6 KiB
Python
187 lines
6.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Standalone unit tests for geocoding lang parameter support.
|
|
No Django project setup needed — all HTTP calls are mocked.
|
|
|
|
Usage:
|
|
cd /home/alex/projects/voyage/backend/server
|
|
python3 test_geocoding_lang.py
|
|
"""
|
|
|
|
import sys
|
|
import json
|
|
import unittest
|
|
from unittest.mock import patch, MagicMock
|
|
import types
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Minimal stubs so geocoding.py can be imported without a full Django project
|
|
# ---------------------------------------------------------------------------
|
|
django_module = types.ModuleType("django")
|
|
django_conf_module = types.ModuleType("django.conf")
|
|
|
|
|
|
class _Settings:
|
|
GOOGLE_MAPS_API_KEY = None
|
|
|
|
|
|
settings = _Settings()
|
|
django_conf_module.settings = settings
|
|
django_module.conf = django_conf_module
|
|
sys.modules.setdefault("django", django_module)
|
|
sys.modules.setdefault("django.conf", django_conf_module)
|
|
|
|
# Stub worldtravel models (not used by the functions under test)
|
|
for mod_name in ("worldtravel", "worldtravel.models"):
|
|
m = types.ModuleType(mod_name)
|
|
for attr in ("Region", "City", "VisitedRegion", "VisitedCity"):
|
|
setattr(m, attr, None)
|
|
sys.modules.setdefault(mod_name, m)
|
|
|
|
sys.path.insert(0, "/home/alex/projects/voyage/backend/server")
|
|
from adventures.geocoding import search_osm, search_google # noqa: E402
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Helpers
|
|
# ---------------------------------------------------------------------------
|
|
def _mock_response(json_data, status_code=200):
|
|
r = MagicMock()
|
|
r.json.return_value = json_data
|
|
r.raise_for_status.return_value = None
|
|
r.status_code = status_code
|
|
return r
|
|
|
|
|
|
_OSM_RESULT = [
|
|
{
|
|
"lat": "50.0755",
|
|
"lon": "14.4378",
|
|
"name": "Prague",
|
|
"display_name": "Prague, Czech Republic",
|
|
"type": "city",
|
|
"category": "place",
|
|
"importance": 0.9,
|
|
"addresstype": "city",
|
|
}
|
|
]
|
|
|
|
_GOOGLE_RESULT = {
|
|
"places": [
|
|
{
|
|
"displayName": {"text": "Prague"},
|
|
"formattedAddress": "Prague, Czech Republic",
|
|
"location": {"latitude": 50.0755, "longitude": 14.4378},
|
|
"types": ["locality"],
|
|
"rating": 4.5,
|
|
"userRatingCount": 1000,
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Tests: search_osm (Nominatim)
|
|
# ---------------------------------------------------------------------------
|
|
class TestSearchOsmLang(unittest.TestCase):
|
|
def test_explicit_lang_en(self):
|
|
"""search_osm('Prague', lang='en') sends Accept-Language: en"""
|
|
with patch(
|
|
"requests.get", return_value=_mock_response(_OSM_RESULT)
|
|
) as mock_get:
|
|
search_osm("Prague", lang="en")
|
|
headers = mock_get.call_args[1].get("headers", {})
|
|
self.assertEqual(headers.get("Accept-Language"), "en")
|
|
|
|
def test_explicit_lang_de(self):
|
|
"""search_osm('Prague', lang='de') sends Accept-Language: de"""
|
|
with patch("requests.get", return_value=_mock_response([])) as mock_get:
|
|
search_osm("Prague", lang="de")
|
|
headers = mock_get.call_args[1].get("headers", {})
|
|
self.assertEqual(headers.get("Accept-Language"), "de")
|
|
|
|
def test_default_lang_is_en(self):
|
|
"""search_osm('Prague') without lang defaults to Accept-Language: en"""
|
|
with patch("requests.get", return_value=_mock_response([])) as mock_get:
|
|
search_osm("Prague")
|
|
headers = mock_get.call_args[1].get("headers", {})
|
|
self.assertEqual(
|
|
headers.get("Accept-Language"),
|
|
"en",
|
|
f"Expected 'en', got {headers.get('Accept-Language')!r}",
|
|
)
|
|
|
|
def test_returns_list(self):
|
|
"""search_osm returns a list"""
|
|
with patch("requests.get", return_value=_mock_response(_OSM_RESULT)):
|
|
result = search_osm("Prague", lang="en")
|
|
self.assertIsInstance(result, list)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Tests: search_google (Google Places)
|
|
# ---------------------------------------------------------------------------
|
|
class TestSearchGoogleLang(unittest.TestCase):
|
|
def setUp(self):
|
|
settings.GOOGLE_MAPS_API_KEY = "test-api-key"
|
|
|
|
def tearDown(self):
|
|
settings.GOOGLE_MAPS_API_KEY = None
|
|
|
|
def test_explicit_lang_en(self):
|
|
"""search_google('Prague', lang='en') posts languageCode: 'en'"""
|
|
with patch(
|
|
"requests.post", return_value=_mock_response(_GOOGLE_RESULT)
|
|
) as mock_post:
|
|
search_google("Prague", lang="en")
|
|
payload = mock_post.call_args[1].get("json", {})
|
|
self.assertIn("languageCode", payload)
|
|
self.assertEqual(payload["languageCode"], "en")
|
|
|
|
def test_explicit_lang_fr(self):
|
|
"""search_google('Prague', lang='fr') posts languageCode: 'fr'"""
|
|
with patch(
|
|
"requests.post", return_value=_mock_response(_GOOGLE_RESULT)
|
|
) as mock_post:
|
|
search_google("Prague", lang="fr")
|
|
payload = mock_post.call_args[1].get("json", {})
|
|
self.assertEqual(payload.get("languageCode"), "fr")
|
|
|
|
def test_default_lang_is_en(self):
|
|
"""search_google('Prague') without lang defaults to languageCode: 'en'"""
|
|
with patch(
|
|
"requests.post", return_value=_mock_response(_GOOGLE_RESULT)
|
|
) as mock_post:
|
|
search_google("Prague")
|
|
payload = mock_post.call_args[1].get("json", {})
|
|
self.assertEqual(
|
|
payload.get("languageCode"),
|
|
"en",
|
|
f"Expected 'en', got {payload.get('languageCode')!r}",
|
|
)
|
|
|
|
def test_returns_list(self):
|
|
"""search_google returns a list"""
|
|
with patch("requests.post", return_value=_mock_response(_GOOGLE_RESULT)):
|
|
result = search_google("Prague", lang="en")
|
|
self.assertIsInstance(result, list)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
if __name__ == "__main__":
|
|
print("=" * 60)
|
|
print("Geocoding lang parameter — unit tests")
|
|
print("=" * 60)
|
|
runner = unittest.TextTestRunner(verbosity=2)
|
|
suite = unittest.TestLoader().loadTestsFromNames(
|
|
["__main__.TestSearchOsmLang", "__main__.TestSearchGoogleLang"]
|
|
)
|
|
result = runner.run(suite)
|
|
print("=" * 60)
|
|
if result.wasSuccessful():
|
|
print(f"ALL {result.testsRun} TESTS PASSED ✓")
|
|
sys.exit(0)
|
|
else:
|
|
print(f"FAILURES: {len(result.failures)}, ERRORS: {len(result.errors)}")
|
|
sys.exit(1)
|