import pytest from pydantic import ValidationError from webapp.app import SimulateRequest, app, health, simulate def test_health_endpoint(): payload = health() assert payload["ok"] is True assert payload["version"] == "0.4.7" def test_simulation_endpoint_preserves_equal_budget(): payload = simulate( SimulateRequest( rng_seed=3, n_paths=5, n_steps=100, drop_fraction=0.05, rise_fraction=0.08, max_detection_lag_steps=3, ) ) assert payload["adaptive_total_samples"] == payload["fixed_total_samples"] assert payload["max_detection_lag_steps"] == 3 def test_webapp_imports_from_source_checkout_without_installed_package(tmp_path): """The documented direct uvicorn command must resolve the src-layout package.""" import os import subprocess import sys from pathlib import Path repo_root = Path(__file__).resolve().parents[1] env = os.environ.copy() env.pop("PYTHONPATH", None) completed = subprocess.run( [sys.executable, "-c", "import webapp.app; print(webapp.app.app.title)"], cwd=repo_root, env=env, capture_output=True, text=True, check=False, ) assert completed.returncode == 0, completed.stderr assert "Adaptive Barrier Monitor" in completed.stdout def test_simulation_endpoint_supports_fixed_cadence(): payload = simulate( SimulateRequest( rng_seed=3, n_paths=5, n_steps=200, window_minutes=200.0, dt_cap_minutes=2.0, comparison_mode="fixed_cadence", fixed_cadence_minutes=20.0, ) ) assert payload["comparison_mode"] == "fixed_cadence" assert payload["fixed_cadence_minutes"] == 20.0 assert payload["adaptive_total_samples"] != payload["fixed_total_samples"] def test_simulation_endpoint_rejects_unknown_comparison_mode(): with pytest.raises(ValidationError): SimulateRequest.model_validate({"comparison_mode": "unknown"}) def test_app_registers_expected_routes(): route_methods = { route.path: getattr(route, "methods", set()) for route in app.routes } assert "GET" in route_methods["/api/health"] assert "POST" in route_methods["/api/simulate"]