- Add vitest config and unit tests for components, api, stores - Add Playwright e2e test for user flows - Add backend test files - Update risk.py with LOD grid KDTree optimization
113 lines
4.1 KiB
Python
113 lines
4.1 KiB
Python
"""US-002: Error handling and edge case tests."""
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
class TestDateValidation:
|
|
def test_invalid_date_format_alerts(self, client: TestClient):
|
|
resp = client.get("/api/alerts?date=invalid")
|
|
assert resp.status_code == 400
|
|
data = resp.json()
|
|
assert "detail" in data
|
|
|
|
def test_invalid_alert_date_format_detail(self, client: TestClient):
|
|
resp = client.get("/api/alerts/nonexistent?date=notadate")
|
|
assert resp.status_code == 400
|
|
|
|
def test_malformed_query_params(self, client: TestClient):
|
|
"""Non-numeric value for numeric param should return 422."""
|
|
resp = client.get("/api/risk/lod-grid?zoom=abc")
|
|
assert resp.status_code == 422
|
|
|
|
|
|
class TestMissingResources:
|
|
def test_nonexistent_endpoint(self, client: TestClient):
|
|
resp = client.get("/api/nonexistent_endpoint_xyz")
|
|
assert resp.status_code == 404
|
|
|
|
def test_nonexistent_grid_history(self, client: TestClient):
|
|
resp = client.get("/api/risk/history/nonexistent_grid_99999")
|
|
assert resp.status_code == 404
|
|
|
|
def test_nonexistent_date(self, client: TestClient):
|
|
resp = client.get("/api/risk/map?date=20990101")
|
|
assert resp.status_code == 404
|
|
assert "detail" in resp.json()
|
|
|
|
|
|
class TestInvalidForecastDay:
|
|
def test_forecast_out_of_range(self, client: TestClient):
|
|
resp = client.get("/api/risk/forecast/0")
|
|
assert resp.status_code in (200, 404)
|
|
|
|
def test_forecast_too_large(self, client: TestClient):
|
|
resp = client.get("/api/risk/forecast/999")
|
|
assert resp.status_code in (200, 404, 422)
|
|
|
|
def test_lod_grid_invalid_zoom(self, client: TestClient):
|
|
resp = client.get("/api/risk/lod-grid?zoom=0")
|
|
assert resp.status_code == 422
|
|
|
|
def test_lod_grid_zoom_too_high(self, client: TestClient):
|
|
resp = client.get("/api/risk/lod-grid?zoom=21")
|
|
assert resp.status_code == 422
|
|
|
|
def test_lod_tile_below_min_zoom(self, client: TestClient):
|
|
resp = client.get("/api/risk/lod-grid/tile?zoom=10&tile_x=0&tile_y=0&forecast_day=1")
|
|
assert resp.status_code in (400, 422)
|
|
|
|
|
|
class TestAuthRequiredEndpoints:
|
|
def test_me_without_token(self, client: TestClient):
|
|
resp = client.get("/api/auth/me")
|
|
assert resp.status_code in (401, 403)
|
|
|
|
|
|
class TestMalformedRequestBody:
|
|
def test_login_missing_fields(self, client: TestClient):
|
|
resp = client.post("/api/auth/login", json={})
|
|
assert resp.status_code == 422
|
|
|
|
def test_login_empty_body(self, client: TestClient):
|
|
resp = client.post("/api/auth/login")
|
|
assert resp.status_code == 422
|
|
|
|
def test_chat_missing_messages(self, client: TestClient):
|
|
resp = client.post("/api/chat", json={})
|
|
assert resp.status_code in (403, 422)
|
|
|
|
def test_predict_missing_date(self, client: TestClient):
|
|
resp = client.post("/api/predict/multi-day", json={"days": 3})
|
|
assert resp.status_code == 422
|
|
|
|
def test_predict_invalid_days(self, client: TestClient):
|
|
resp = client.post("/api/predict/multi-day", json={"date": "2022-12-15", "days": 0})
|
|
assert resp.status_code == 422
|
|
|
|
|
|
class TestGlobalErrorHandler:
|
|
def test_internal_error_returns_json(self, client: TestClient):
|
|
"""Global exception handler should return JSON, not HTML, on 500."""
|
|
resp = client.get("/api/risk/lod-grid?zoom=10&forecast_day=1")
|
|
assert resp.status_code == 200 # valid request should pass
|
|
|
|
|
|
class TestCORSAvailability:
|
|
def test_cors_preflight(self, client: TestClient):
|
|
resp = client.options(
|
|
"/api/risk/current",
|
|
headers={
|
|
"Origin": "http://localhost:5173",
|
|
"Access-Control-Request-Method": "GET",
|
|
},
|
|
)
|
|
assert resp.status_code == 200
|
|
|
|
def test_cors_origin_header(self, client: TestClient):
|
|
resp = client.get(
|
|
"/api/risk/current",
|
|
headers={"Origin": "http://localhost:5173"},
|
|
)
|
|
assert resp.status_code == 200
|
|
assert "access-control-allow-origin" in resp.headers
|