soupstick's picture
fix: redirect space root to docs
530290c
Raw
History Blame Contribute Delete
2.99 kB
import json
import time
import pytest
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
with open("tests/fixtures/test_queries.json", encoding="utf-8") as fixture_file:
test_cases = json.load(fixture_file)["test_cases"]
def test_root_redirects_to_docs():
response = client.get("/", follow_redirects=False)
assert response.status_code == 307
assert response.headers["location"] == "/docs"
def test_health():
response = client.get("/health")
assert response.status_code == 200
assert response.json()["status"] in ["ok", "degraded"]
assert response.json()["database"] == "connected"
def test_examples_endpoint():
response = client.get("/api/v1/examples")
assert response.status_code == 200
assert len(response.json()["questions"]) >= 10
def test_schema_endpoint():
response = client.get("/api/v1/schema")
assert response.status_code == 200
tables = response.json()["tables"]
for table in ["orders", "customers", "products"]:
assert table in tables
def test_sql_validate_valid():
response = client.post("/api/v1/sql/validate", json={"sql": "SELECT * FROM orders"})
assert response.status_code == 200
assert response.json()["valid"] is True
def test_sql_validate_invalid():
response = client.post("/api/v1/sql/validate", json={"sql": "DROP TABLE orders"})
assert response.status_code == 200
assert response.json()["valid"] is False
@pytest.mark.parametrize("tc", test_cases[:12])
def test_query_endpoint(tc):
response = client.post("/api/v1/query", json={"question": tc["question"]})
assert response.status_code == 200
body = response.json()
assert body["sql_valid"] is True, f"[{tc['id']}] SQL invalid for: {tc['question']}\nError: {body.get('error')}"
assert body["result_rows"] >= tc["expected_min_rows"], (
f"[{tc['id']}] Got {body['result_rows']} rows, expected >= {tc['expected_min_rows']}"
)
for field in [
"query_id",
"generated_sql",
"sql_source",
"sql_valid",
"result_rows",
"data",
"latency_ms",
]:
assert field in body, f"Missing field: {field}"
def test_query_invalid_request():
response = client.post("/api/v1/query", json={"question": ""})
assert response.status_code == 422
def test_query_sql_injection_attempt():
response = client.post("/api/v1/query", json={"question": "DROP TABLE orders; --"})
assert response.status_code == 200
body = response.json()
if not body["sql_valid"]:
assert body["error"] is not None
else:
assert "DROP" not in body["generated_sql"].upper()
def test_query_latency():
start = time.time()
response = client.post("/api/v1/query", json={"question": "top products by revenue"})
elapsed = (time.time() - start) * 1000
assert elapsed < 3000, f"Latency {elapsed:.0f}ms exceeds 3000ms"
assert response.json()["latency_ms"] < 3000