"""Non-regression of the historical v1 surface: same paths, same shapes, same status codes.""" def test_health(client): r = client.get("/health") assert r.status_code == 200 assert r.json()["status"] == "ok" def test_status_lists_assets(client): r = client.get("/v1/status") assert r.status_code == 200 body = r.json() assert "datasets" in body and "stock" in body["datasets"] def test_tickers_and_bars_shape(client): r = client.get("/v1/stock/tickers?timeframe=1day") assert r.status_code == 200 assert "AAPL" in r.json()["tickers"] r = client.get("/v1/bars/stock/AAPL?timeframe=1day&limit=5") assert r.status_code == 200 body = r.json() assert body["count"] == 5 and set(body["data"][0]) >= {"ticker", "datetime", "open", "high", "low", "close", "volume"} assert r.headers["X-Row-Count"] == "5" def test_csv_format(client): r = client.get("/v1/bars/stock/AAPL?timeframe=1day&limit=3&format=csv") assert r.status_code == 200 and r.headers["content-type"].startswith("text/csv") assert r.text.splitlines()[0].startswith("ticker,datetime") def test_uniform_error_envelope_keeps_legacy_detail(client): r = client.get("/v1/bars/stock/NOPE?timeframe=1day") assert r.status_code == 404 body = r.json() assert body["error"]["code"] == "TICKER_NOT_FOUND" assert body["error"]["docs"].endswith("#ticker_not_found") assert body["detail"] # legacy field still present def test_validation_error_is_uniform(client): r = client.get("/v1/bars/stock/AAPL?timeframe=1day&limit=0") assert r.status_code == 422 assert r.json()["error"]["code"] == "VALIDATION_ERROR" def test_options_chain(client): r = client.get("/v1/options/chain/AAPL?limit=4") assert r.status_code == 200 assert r.json()["count"] == 4