SaarthiAI / tests /test_tools_misc.py
parthmax24's picture
working proto 5
8b96826
Raw
History Blame Contribute Delete
9.11 kB
"""Geocode, festivals, events, advisories tools with mocked HTTP."""
import requests as requests_lib
import pytest
from app.tools import advisories, events, festivals, geocode
# ---- geocode ----------------------------------------------------------------
def test_geocode_returns_best_match(monkeypatch, fake_response, fake_keys):
captured = {"urls": [], "params": []}
def fake_get(url, params=None, timeout=None):
captured["urls"].append(url)
captured["params"].append(params)
return fake_response(
{
"results": [
{
"position": {"lat": 26.8512, "lon": 80.9462},
"address": {"freeformAddress": "Hazratganj, Lucknow"},
"poi": {"name": "Hazratganj Market"},
}
]
}
)
monkeypatch.setattr(geocode.requests, "get", fake_get)
result = geocode.geocode_place("Hazratganj")
assert result["lat"] == 26.8512
assert result["name"] == "Hazratganj Market"
assert any("Lucknow" in url for url in captured["urls"]) # query is city-biased
assert captured["params"][0]["countrySet"] == "IN"
def test_geocode_no_results_raises(monkeypatch, fake_response, fake_keys):
monkeypatch.setattr(geocode.requests, "get", lambda *a, **k: fake_response({"results": []}))
with pytest.raises(RuntimeError, match="No location found"):
geocode.geocode_place("Nonexistent Place XYZ")
def test_geocode_prefers_poi_over_city_geography(monkeypatch, fake_response, fake_keys):
"""'iiit lucknow' must resolve to the campus POI, not Lucknow city center."""
payload = {
"results": [
{ # the city itself — this used to win and wreck all ETAs
"type": "Geography",
"position": {"lat": 26.8467, "lon": 80.9462},
"address": {"freeformAddress": "Lucknow, Uttar Pradesh"},
},
{
"type": "POI",
"position": {"lat": 26.7991, "lon": 81.0220},
"address": {"freeformAddress": "IIIT Lucknow, Ahmamau"},
"poi": {"name": "Indian Institute of Information Technology Lucknow"},
},
]
}
monkeypatch.setattr(geocode.requests, "get", lambda *a, **k: fake_response(payload))
result = geocode.geocode_place("iiit lucknow")
assert result["lat"] == 26.7991
assert "Information Technology" in result["name"]
def test_geocode_falls_back_to_geography_when_nothing_else(monkeypatch, fake_response, fake_keys):
payload = {
"results": [
{
"type": "Geography",
"position": {"lat": 26.8467, "lon": 80.9462},
"address": {"freeformAddress": "Lucknow, Uttar Pradesh"},
}
]
}
monkeypatch.setattr(geocode.requests, "get", lambda *a, **k: fake_response(payload))
result = geocode.geocode_place("Lucknow")
assert result["lat"] == 26.8467
def test_geocode_rejects_results_outside_lucknow(monkeypatch, fake_response, fake_keys):
payload = {
"results": [
{ # a match in Delhi — must not be accepted
"type": "POI",
"position": {"lat": 28.6139, "lon": 77.2090},
"address": {"freeformAddress": "Connaught Place, Delhi"},
"poi": {"name": "Some Place Delhi"},
}
]
}
monkeypatch.setattr(geocode.requests, "get", lambda *a, **k: fake_response(payload))
with pytest.raises(RuntimeError, match="No location found"):
geocode.geocode_place("Some Place")
def test_geocode_no_double_city_suffix(monkeypatch, fake_response, fake_keys):
captured = {"urls": []}
def fake_get(url, params=None, timeout=None):
captured["urls"].append(url)
return fake_response(
{
"results": [
{
"type": "POI",
"position": {"lat": 26.80, "lon": 81.02},
"address": {"freeformAddress": "IIIT Lucknow"},
"poi": {"name": "IIIT Lucknow"},
}
]
}
)
monkeypatch.setattr(geocode.requests, "get", fake_get)
geocode.geocode_place("iiit lucknow")
# Input already contains 'lucknow' -> the city suffix must NOT be appended
assert "Uttar%20Pradesh" not in captured["urls"][0]
# ---- festivals ----------------------------------------------------------------
def test_festivals_merges_calendarific_and_curated(monkeypatch, fake_response, fake_keys):
calendarific_payload = {
"meta": {"code": 200},
"response": {
"holidays": [
{
"name": "Some National Holiday",
"description": "A big holiday",
"date": {"iso": "2026-06-09"},
"type": ["National holiday"],
}
]
},
}
monkeypatch.setattr(
festivals.requests, "get", lambda *a, **k: fake_response(calendarific_payload)
)
# 2026-06-09 is a Bada Mangal Tuesday -> curated event must appear too
result = festivals.get_festivals("2026-06-09")
names = [festival["name"] for festival in result["festivals"]]
assert "Some National Holiday" in names
assert "Bada Mangal" in names
assert result["impact"] == 2 # very_high from Bada Mangal
def test_festivals_survives_api_failure(monkeypatch, fake_keys):
def boom(*args, **kwargs):
raise requests_lib.ConnectionError("network down")
monkeypatch.setattr(festivals.requests, "get", boom)
result = festivals.get_festivals("2026-03-02") # no curated events that day
assert result["festivals"] == []
assert result["impact"] == 0
# ---- events ----------------------------------------------------------------
def test_events_classifies_stadium_as_high_impact(monkeypatch, fake_response, fake_keys):
payload = {
"_embedded": {
"events": [
{
"name": "IPL Match",
"dates": {"start": {"localTime": "19:30:00"}},
"_embedded": {"venues": [{"name": "Ekana Cricket Stadium"}]},
}
]
}
}
monkeypatch.setattr(events.requests, "get", lambda *a, **k: fake_response(payload))
result = events.get_events("2026-06-12")
assert result["impact"] == 2
assert result["events"][0]["traffic_impact"] == "high"
def test_events_empty_when_api_fails(monkeypatch, fake_keys):
def boom(*args, **kwargs):
raise requests_lib.Timeout("slow")
monkeypatch.setattr(events.requests, "get", boom)
result = events.get_events("2026-06-12")
assert result == {"events": [], "impact": 0}
def test_events_empty_without_key(monkeypatch):
from app import config
monkeypatch.setattr(config, "ticketmaster_key", lambda: None)
result = events.get_events("2026-06-12")
assert result == {"events": [], "impact": 0}
# ---- advisories ----------------------------------------------------------------
def test_advisories_parses_relevant_results(monkeypatch, fake_response):
html = """
<a class="result__a" href="#">Lucknow traffic police announces route diversion for procession</a>
<a class="result__snippet" href="#">Roads near Chowk will remain closed on Friday evening...</a>
<a class="result__a" href="#">Weather in Mumbai today</a>
<a class="result__snippet" href="#">Sunny skies expected across the city</a>
"""
monkeypatch.setattr(
advisories.requests, "post", lambda *a, **k: fake_response(text=html)
)
result = advisories.get_police_advisories()
assert result["count"] == 1
assert "diversion" in result["advisories"][0]["title"].lower()
assert result["advisories"][0]["title"].startswith("News:")
def test_advisories_searches_past_week_and_unescapes(monkeypatch, fake_response):
captured = {}
def fake_post(url, data=None, headers=None, timeout=None):
captured["data"] = data
html = (
'<a class="result__a" href="#">Lucknow &quot;Bada Mangal&quot; route diversion advisory</a>'
'<a class="result__snippet" href="#">Roads closed near Aliganj &amp; Hazratganj</a>'
)
return fake_response(text=html)
monkeypatch.setattr(advisories.requests, "post", fake_post)
result = advisories.get_police_advisories()
assert captured["data"]["df"] == "w" # past-week filter is on
assert '"' in result["advisories"][0]["title"] # &quot; unescaped
assert "&quot;" not in result["advisories"][0]["title"]
assert "&amp;" not in result["advisories"][0]["detail"]
def test_advisories_empty_on_network_failure(monkeypatch):
def boom(*args, **kwargs):
raise requests_lib.ConnectionError("blocked")
monkeypatch.setattr(advisories.requests, "post", boom)
result = advisories.get_police_advisories()
assert result == {"advisories": [], "count": 0}