diff --git a/frontend/src/pages/ResultsPage.tsx b/frontend/src/pages/ResultsPage.tsx index b5d0a81..2d63a14 100644 --- a/frontend/src/pages/ResultsPage.tsx +++ b/frontend/src/pages/ResultsPage.tsx @@ -39,8 +39,6 @@ export function ResultsPage() { const [error, setError] = useState(null) const trackIntervalOptions = useMemo(() => [ - { value: 1, label: t('common.checkEveryMin', { n: 1 }) }, - { value: 5, label: t('common.checkEveryMin', { n: 5 }) }, { value: 10, label: t('common.checkEveryMin', { n: 10 }) }, { value: 30, label: t('common.checkEveryMin', { n: 30 }) }, { value: 60, label: t('common.checkEveryHour', { n: 1 }) }, diff --git a/tests/test_notifications_api.py b/tests/test_notifications_api.py index f9f63c2..ae314cc 100644 --- a/tests/test_notifications_api.py +++ b/tests/test_notifications_api.py @@ -18,7 +18,7 @@ def test_build_price_change_summary_format() -> None: old_price=10.0, new_price=12.5, ) - assert summary == "Trip - Madrid -> Zaragoza, 09:30, changed price from 10.00 to 12.50" + assert summary == "Price changed: Madrid → Zaragoza, dep. 09:30. Price: €10.00 → €12.50" def test_build_price_change_summary_old_price_unknown() -> None: @@ -29,7 +29,7 @@ def test_build_price_change_summary_old_price_unknown() -> None: old_price=None, new_price=12.5, ) - assert summary == "Trip - Madrid -> Zaragoza, N/A, changed price from N/A to 12.50" + assert summary == "Price changed: Madrid → Zaragoza, dep. N/A. Price: N/A → €12.50" def test_notifications_email_crud(client: TestClient) -> None: @@ -93,11 +93,11 @@ def test_notifications_browser_crud(client: TestClient) -> None: def test_notifications_home_assistant_crud_and_masking(client: TestClient) -> None: + # HA URL and token are configured via env vars, not stored in DB. + # Only ha_notify_service is user-facing and stored. payload = { "type": "home_assistant", "label": "HA notifier", - "ha_url": "http://localhost:8123", - "ha_token": "super-secret-token", "ha_notify_service": "mobile_app_javier", } @@ -111,9 +111,8 @@ def test_notifications_home_assistant_crud_and_masking(client: TestClient) -> No notif = next(n for n in notifications if n["id"] == notification_id) assert notif["type"] == "home_assistant" - assert notif["ha_url"] == "http://localhost:8123" - assert notif["notify_service"] == "mobile_app_javier" - assert notif["has_ha_token"] is True + assert notif["ha_notify_service"] == "mobile_app_javier" + assert "ha_url" not in notif assert "ha_token" not in notif removed = client.delete(f"/api/notifications/{notification_id}") @@ -122,16 +121,12 @@ def test_notifications_home_assistant_crud_and_masking(client: TestClient) -> No def test_notifications_email_public_list_returns_masked_secret_indicators(client: TestClient) -> None: + # SMTP credentials are configured via env vars, not stored in DB. + # Only user-facing fields (email_to, email_subject) are stored and returned. payload = { "type": "email", "label": "Masked email", - "smtp_host": "smtp.example.com", - "smtp_port": 587, - "smtp_username": "user@example.com", - "smtp_password": "super-secret-password", - "smtp_use_starttls": True, "email_to": "to@example.com", - "email_from": "from@example.com", "email_subject": "Price change alert", } @@ -144,9 +139,10 @@ def test_notifications_email_public_list_returns_masked_secret_indicators(client notifications = listed.json().get("notifications", []) notif = next(n for n in notifications if n["id"] == notification_id) - assert notif["smtp_username"] == "******" - assert notif["has_smtp_password"] is True + assert notif["email_to"] == "to@example.com" + assert notif["email_subject"] == "Price change alert" assert "smtp_password" not in notif + assert "smtp_username" not in notif def test_notifications_init_db_migrates_legacy_notification_columns(tmp_path: Path) -> None: diff --git a/tests/test_search_api.py b/tests/test_search_api.py index 8aa6624..c1df1a6 100644 --- a/tests/test_search_api.py +++ b/tests/test_search_api.py @@ -7,13 +7,16 @@ def test_search_options_includes_zaragoza_calatayud_tafalla(client: TestClient): - """GET /api/search/options must include Zaragoza, Calatayud, Tafalla.""" + """GET /api/search/options must include Zaragoza-Delicias, Calatayud, Tafalla.""" r = client.get("/api/search/options") assert r.status_code == 200 data = r.json() origins = data.get("origins", []) destinations = data.get("destinations", []) - for name in ("Zaragoza", "Calatayud", "Tafalla"): + # Zaragoza has several stations (Delicias, Goya, etc.) but no plain "Zaragoza" + assert any("Zaragoza" in name for name in origins), "Missing any Zaragoza station in origins" + assert any("Zaragoza" in name for name in destinations), "Missing any Zaragoza station in destinations" + for name in ("Calatayud", "Tafalla"): assert name in origins, f"Missing origin: {name}" assert name in destinations, f"Missing destination: {name}" @@ -24,11 +27,12 @@ def test_search_returns_trains_when_backend_mocked(client: TestClient): {"name": "AVE 0101", "price": 45.50, "duration_minutes": 90, "estimated_price_min": None, "estimated_price_max": None}, ] with patch("app.api.search._is_mock_enabled", return_value=False): - with patch("app.api.search._trains_from_gtfs_backend", return_value=mock_trains): - r = client.post( - "/api/search", - json={"date": "2025-06-15", "origin": "Madrid", "destination": "Zaragoza"}, - ) + with patch("app.api.search._is_possible_trains_enabled", return_value=False): + with patch("app.api.search._trains_from_gtfs_backend", return_value=mock_trains): + r = client.post( + "/api/search", + json={"date": "2025-06-15", "origin": "Madrid", "destination": "Zaragoza"}, + ) assert r.status_code == 200 data = r.json() assert "trains" in data @@ -40,11 +44,12 @@ def test_search_returns_trains_when_backend_mocked(client: TestClient): def test_search_returns_503_when_backend_fails(client: TestClient): """POST /api/search returns 503 when GTFS backend raises an exception.""" with patch("app.api.search._is_mock_enabled", return_value=False): - with patch("app.api.search._trains_from_gtfs_backend", side_effect=Exception("No se pudo conectar con Renfe")): - r = client.post( - "/api/search", - json={"date": "2025-06-15", "origin": "Madrid", "destination": "Barcelona"}, - ) + with patch("app.api.search._is_possible_trains_enabled", return_value=False): + with patch("app.api.search._trains_from_gtfs_backend", side_effect=Exception("No se pudo conectar con Renfe")): + r = client.post( + "/api/search", + json={"date": "2025-06-15", "origin": "Madrid", "destination": "Barcelona"}, + ) assert r.status_code == 503 assert "detail" in r.json() assert "Renfe" in r.json()["detail"]