Files
stonks-oracle/tests/integration/test_query_api.py
T
Celes Renata c85c0068a2 fix: clean up utcnow deprecation warnings, fix 12 failing tests, add CI/CD pipeline manifests
- Replace all datetime.utcnow() with datetime.now(tz=timezone.utc) across 8 files
- Fix 12 failing tests to match current implementation behavior
- Fix pytest_plugins in non-top-level conftest (moved to root conftest.py)
- Auto-fix 189 lint issues (import sorting, unused imports)
- Add CI/CD pipeline infrastructure (ARC, ArgoCD, Kargo manifests)
- Add values-beta.yaml and values-paper.yaml for staged deployments
- Update GitHub Actions workflow to use self-hosted-gremlin runners
- Add integration-test job to CI pipeline

Result: 1596 passed, 0 failed, 0 warnings
2026-04-18 03:59:28 +00:00

289 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Integration tests for the Query API — all 17 frontend-facing endpoints.
Validates every GET endpoint the frontend calls against the live sandbox
with deterministic seed data. Uses the ``query_client`` and ``seed_ids``
fixtures from conftest.py.
"""
import pytest
pytestmark = pytest.mark.asyncio
# ---------------------------------------------------------------------------
# 13 Companies
# ---------------------------------------------------------------------------
class TestQueryAPICompanies:
"""Endpoints: /api/companies, /api/companies/{id}, /api/companies/{id}/sources."""
async def test_list_companies(self, query_client, seed_ids):
"""GET /api/companies — expect at least 5 seeded companies."""
resp = await query_client.get("/api/companies")
assert resp.status_code == 200
data = resp.json()
assert len(data) >= 5
tickers = {c["ticker"] for c in data}
assert {"AAPL", "MSFT", "JPM", "JNJ", "XOM"} <= tickers
# Every company row must have core fields
for c in data:
assert "id" in c
assert "legal_name" in c
assert "sector" in c
async def test_get_company(self, query_client, seed_ids):
"""GET /api/companies/{id} — detail for AAPL."""
company_id = seed_ids["companies"]["AAPL"]
resp = await query_client.get(f"/api/companies/{company_id}")
assert resp.status_code == 200
data = resp.json()
assert data["ticker"] == "AAPL"
assert data["legal_name"] == "Apple Inc"
assert "aliases" in data
assert "active_source_count" in data
async def test_list_company_sources(self, query_client, seed_ids):
"""GET /api/companies/{id}/sources — AAPL has at least 1 source."""
company_id = seed_ids["companies"]["AAPL"]
resp = await query_client.get(f"/api/companies/{company_id}/sources")
assert resp.status_code == 200
data = resp.json()
assert isinstance(data, list)
assert len(data) >= 1
assert "source_type" in data[0]
# ---------------------------------------------------------------------------
# 45 Documents
# ---------------------------------------------------------------------------
class TestQueryAPIDocuments:
"""Endpoints: /api/documents, /api/documents/{id}."""
async def test_list_documents(self, query_client, seed_ids):
"""GET /api/documents — expect at least 10 seeded documents."""
resp = await query_client.get("/api/documents")
assert resp.status_code == 200
data = resp.json()
assert len(data) >= 10
for doc in data:
assert "id" in doc
assert "document_type" in doc
assert "title" in doc
async def test_get_document(self, query_client, seed_ids):
"""GET /api/documents/{id} — detail with intelligence."""
doc_id = seed_ids["documents"]["DOC_01"]
resp = await query_client.get(f"/api/documents/{doc_id}")
assert resp.status_code == 200
data = resp.json()
assert data["id"] == doc_id
assert "title" in data
assert "document_type" in data
# Intelligence extraction should be present for seeded docs
assert "intelligence" in data
assert "company_mentions" in data
# ---------------------------------------------------------------------------
# 67 Trends
# ---------------------------------------------------------------------------
class TestQueryAPITrends:
"""Endpoints: /api/trends, /api/trends/{id}."""
async def test_list_trends(self, query_client, seed_ids):
"""GET /api/trends — expect at least 5 seeded trend windows."""
resp = await query_client.get("/api/trends")
assert resp.status_code == 200
data = resp.json()
assert len(data) >= 5
for t in data:
assert "id" in t
assert "trend_direction" in t
assert "confidence" in t
async def test_get_trend(self, query_client, seed_ids):
"""GET /api/trends/{id} — detail for first seeded trend."""
trend_id = seed_ids["trends"]["TREND_01"]
resp = await query_client.get(f"/api/trends/{trend_id}")
assert resp.status_code == 200
data = resp.json()
assert data["id"] == trend_id
assert data["trend_direction"] in ("bullish", "bearish", "mixed")
assert 0 <= data["confidence"] <= 1
# ---------------------------------------------------------------------------
# 89 Recommendations
# ---------------------------------------------------------------------------
class TestQueryAPIRecommendations:
"""Endpoints: /api/recommendations, /api/recommendations/{id}."""
async def test_list_recommendations(self, query_client, seed_ids):
"""GET /api/recommendations — expect at least 5 seeded recs."""
resp = await query_client.get("/api/recommendations", params={"latest": "false"})
assert resp.status_code == 200
data = resp.json()
assert len(data) >= 5
for r in data:
assert "id" in r
assert "ticker" in r
assert "action" in r
assert "confidence" in r
async def test_get_recommendation(self, query_client, seed_ids):
"""GET /api/recommendations/{id} — detail with evidence."""
rec_id = seed_ids["recommendations"]["REC_01"]
resp = await query_client.get(f"/api/recommendations/{rec_id}")
assert resp.status_code == 200
data = resp.json()
assert data["id"] == rec_id
assert "ticker" in data
assert "thesis" in data
assert "evidence" in data
assert "risk_evaluation" in data
# ---------------------------------------------------------------------------
# 1011 Orders
# ---------------------------------------------------------------------------
class TestQueryAPIOrders:
"""Endpoints: /api/orders, /api/orders/{id}."""
async def test_list_orders(self, query_client, seed_ids):
"""GET /api/orders — expect at least 3 seeded orders."""
resp = await query_client.get("/api/orders")
assert resp.status_code == 200
data = resp.json()
assert len(data) >= 3
statuses = {o["status"] for o in data}
# Seed has filled, pending, cancelled
assert len(statuses) >= 2
for o in data:
assert "id" in o
assert "ticker" in o
assert "side" in o
async def test_get_order(self, query_client, seed_ids):
"""GET /api/orders/{id} — detail with events and audit trail."""
order_id = seed_ids["orders"]["ORDER_01"]
resp = await query_client.get(f"/api/orders/{order_id}")
assert resp.status_code == 200
data = resp.json()
assert data["id"] == order_id
assert "ticker" in data
assert "events" in data
assert isinstance(data["events"], list)
assert "audit_trail" in data
# ---------------------------------------------------------------------------
# 12 Positions
# ---------------------------------------------------------------------------
class TestQueryAPIPositions:
"""Endpoint: /api/positions."""
async def test_list_positions(self, query_client, seed_ids):
"""GET /api/positions — expect at least 2 seeded positions."""
resp = await query_client.get("/api/positions")
assert resp.status_code == 200
data = resp.json()
assert len(data) >= 2
for p in data:
assert "id" in p
assert "ticker" in p
assert "quantity" in p
assert "unrealized_pnl" in p
# ---------------------------------------------------------------------------
# 13 Pipeline Health
# ---------------------------------------------------------------------------
class TestQueryAPIOps:
"""Endpoints: /api/ops/pipeline/health, /api/ops/ingestion/summary, /api/ops/sources/coverage-gaps."""
async def test_pipeline_health(self, query_client, seed_ids):
"""GET /api/ops/pipeline/health — returns structured health data."""
resp = await query_client.get("/api/ops/pipeline/health")
assert resp.status_code == 200
data = resp.json()
assert "hours" in data
assert "document_stages" in data
assert "parsing" in data
assert "extraction" in data
assert "aggregation" in data
assert "queue_depths" in data
# -----------------------------------------------------------------------
# 14 Ingestion Summary
# -----------------------------------------------------------------------
async def test_ingestion_summary(self, query_client, seed_ids):
"""GET /api/ops/ingestion/summary — returns ingestion stats."""
resp = await query_client.get("/api/ops/ingestion/summary")
assert resp.status_code == 200
data = resp.json()
assert "hours" in data
assert "total_runs" in data
assert "by_source_type" in data
assert isinstance(data["by_source_type"], list)
# -----------------------------------------------------------------------
# 15 Coverage Gaps
# -----------------------------------------------------------------------
async def test_coverage_gaps(self, query_client, seed_ids):
"""GET /api/ops/sources/coverage-gaps — returns gap analysis."""
resp = await query_client.get("/api/ops/sources/coverage-gaps")
assert resp.status_code == 200
data = resp.json()
assert "missing_source_types" in data
assert "stale_sources" in data
assert isinstance(data["missing_source_types"], list)
assert isinstance(data["stale_sources"], list)
# ---------------------------------------------------------------------------
# 1617 Agents & Variants
# ---------------------------------------------------------------------------
class TestQueryAPIAgents:
"""Endpoints: /api/agents, /api/agents/{id}/variants."""
async def test_list_agents(self, query_client, seed_ids):
"""GET /api/agents — expect at least 3 seeded agents."""
resp = await query_client.get("/api/agents")
assert resp.status_code == 200
data = resp.json()
assert len(data) >= 3
for a in data:
assert "id" in a
assert "name" in a
assert "slug" in a
async def test_list_agent_variants(self, query_client, seed_ids):
"""GET /api/agents/{id}/variants — variants for the extractor agent."""
agent_id = seed_ids["agents"]["extractor"]
resp = await query_client.get(f"/api/agents/{agent_id}/variants")
assert resp.status_code == 200
data = resp.json()
assert isinstance(data, list)
assert len(data) >= 1
for v in data:
assert "id" in v
assert "variant_name" in v
assert v["agent_id"] == agent_id