Add location search and polish running route planner
This commit is contained in:
+85
-1
@@ -7,7 +7,7 @@ import pytest
|
||||
from app import create_app
|
||||
from app.extensions import db
|
||||
from app.models import PlannedRoute, User
|
||||
from app.planner_engine import PlannerError, analyse, generate, validate
|
||||
from app.planner_engine import PlannerError, analyse, generate, search_locations, validate
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -223,3 +223,87 @@ def test_old_candidates_cleanup_and_saved_preservation(app, monkeypatch):
|
||||
with app.app_context():
|
||||
assert db.session.get(PlannedRoute, 1) is None
|
||||
assert db.session.get(PlannedRoute, 2).saved
|
||||
|
||||
|
||||
def test_location_search_contract_and_invalid_results(monkeypatch):
|
||||
import json
|
||||
from urllib.parse import parse_qs, urlsplit
|
||||
|
||||
calls = []
|
||||
|
||||
class Reply:
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *_):
|
||||
pass
|
||||
|
||||
def read(self, limit):
|
||||
assert limit == 1_000_001
|
||||
return json.dumps(
|
||||
{
|
||||
"features": [
|
||||
{
|
||||
"geometry": {"type": "Point", "coordinates": [151.2, -33.9]},
|
||||
"properties": {"label": "Park & gardens, Sydney"},
|
||||
},
|
||||
{
|
||||
"geometry": {"type": "Point", "coordinates": [0, 99]},
|
||||
"properties": {"label": "Invalid"},
|
||||
},
|
||||
{"geometry": {"type": "LineString", "coordinates": []}, "properties": {}},
|
||||
]
|
||||
}
|
||||
).encode()
|
||||
|
||||
def fake(req, timeout):
|
||||
calls.append(req)
|
||||
assert timeout == 8
|
||||
return Reply()
|
||||
|
||||
monkeypatch.setattr("app.planner_engine.urlopen", fake)
|
||||
locations = search_locations(
|
||||
{"text": "Park & gardens", "focus": [151, -33]}, "private-test-key"
|
||||
)
|
||||
assert locations == [{"label": "Park & gardens, Sydney", "coordinates": [151.2, -33.9]}]
|
||||
query = parse_qs(urlsplit(calls[0].full_url).query)
|
||||
assert query["text"] == ["Park & gardens"]
|
||||
assert query["size"] == ["5"] and query["focus.point.lon"] == ["151.0"]
|
||||
assert "private-test-key" not in calls[0].full_url
|
||||
assert calls[0].get_header("Authorization") == "private-test-key"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"data", [None, {}, {"text": "ab"}, {"text": "x" * 201}, {"text": "Sydney", "focus": [0, 99]}]
|
||||
)
|
||||
def test_location_search_validation(data):
|
||||
with pytest.raises(PlannerError):
|
||||
search_locations(data, "test")
|
||||
|
||||
|
||||
def test_location_search_login_configuration_and_csrf(app, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
"app.planner.search_locations",
|
||||
lambda data, key: [{"label": "Public park", "coordinates": [151, -33]}],
|
||||
)
|
||||
client = app.test_client()
|
||||
assert client.post("/routes/search", json={"text": "Sydney"}).status_code == 302
|
||||
login(client)
|
||||
response = client.post("/routes/search", json={"text": "Sydney"})
|
||||
assert response.status_code == 200 and response.json["locations"][0]["label"] == "Public park"
|
||||
app.config["WTF_CSRF_ENABLED"] = True
|
||||
assert client.post("/routes/search", json={"text": "Sydney"}).status_code == 400
|
||||
with pytest.raises(PlannerError, match="not connected"):
|
||||
search_locations({"text": "Sydney"}, None)
|
||||
|
||||
|
||||
def test_location_search_failure_is_actionable(monkeypatch):
|
||||
from urllib.error import URLError
|
||||
|
||||
def fail(*_, **__):
|
||||
raise URLError("private provider internals")
|
||||
|
||||
monkeypatch.setattr("app.planner_engine.urlopen", fail)
|
||||
with pytest.raises(PlannerError, match="selecting a point on the map") as error:
|
||||
search_locations({"text": "Sydney"}, "private-key")
|
||||
assert "private" not in str(error.value)
|
||||
|
||||
Reference in New Issue
Block a user