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
This commit is contained in:
Celes Renata
2026-04-18 03:59:28 +00:00
parent 40227a4eb2
commit c85c0068a2
123 changed files with 7221 additions and 405 deletions
+208
View File
@@ -0,0 +1,208 @@
"""Integration tests for the Symbol Registry API — all 8 frontend-facing endpoints.
Validates every endpoint the frontend calls against the live sandbox
with deterministic seed data. Uses the ``registry_client`` and ``seed_ids``
fixtures from conftest.py.
Routes are at the root level (no /api/ prefix):
/companies, /companies/{id}, /companies/{id}/sources,
/companies/{id}/aliases, /companies/{id}/competitors,
/companies/{id}/exposure
"""
import pytest
pytestmark = pytest.mark.asyncio
# ---------------------------------------------------------------------------
# 12 List & Get Companies
# ---------------------------------------------------------------------------
class TestRegistryCompanies:
"""Endpoints: GET /companies, GET /companies/{id}."""
async def test_list_companies(self, registry_client, seed_ids):
"""GET /companies — expect 5 seeded active companies."""
resp = await registry_client.get("/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
for c in data:
assert "id" in c
assert "legal_name" in c
assert "active" in c
async def test_get_company(self, registry_client, seed_ids):
"""GET /companies/{id} — detail for AAPL."""
company_id = seed_ids["companies"]["AAPL"]
resp = await registry_client.get(f"/companies/{company_id}")
assert resp.status_code == 200
data = resp.json()
assert data["ticker"] == "AAPL"
assert data["legal_name"] == "Apple Inc"
assert data["sector"] == "Technology"
assert data["active"] is True
# ---------------------------------------------------------------------------
# 3 Create Company
# ---------------------------------------------------------------------------
class TestRegistryCreateCompany:
"""Endpoint: POST /companies."""
async def test_create_company(self, registry_client, seed_ids):
"""POST /companies — create a new company with ticker TEST."""
payload = {
"ticker": "TEST",
"legal_name": "Test Corp",
"exchange": "NYSE",
"sector": "Technology",
"industry": "Software",
"market_cap_bucket": "small",
}
resp = await registry_client.post("/companies", json=payload)
assert resp.status_code == 201
data = resp.json()
assert data["ticker"] == "TEST"
assert data["legal_name"] == "Test Corp"
assert data["exchange"] == "NYSE"
assert data["sector"] == "Technology"
assert data["active"] is True
assert "id" in data
# ---------------------------------------------------------------------------
# 4 Update Company
# ---------------------------------------------------------------------------
class TestRegistryUpdateCompany:
"""Endpoint: PUT /companies/{id}."""
async def test_update_company_sector(self, registry_client, seed_ids):
"""PUT /companies/{id} — update XOM's sector."""
company_id = seed_ids["companies"]["XOM"]
payload = {
"ticker": "XOM",
"legal_name": "Exxon Mobil Corp",
"exchange": "NYSE",
"sector": "Energy & Utilities",
"industry": "Oil & Gas Integrated",
"market_cap_bucket": "mega",
}
resp = await registry_client.put(f"/companies/{company_id}", json=payload)
assert resp.status_code == 200
data = resp.json()
assert data["sector"] == "Energy & Utilities"
assert data["ticker"] == "XOM"
assert data["id"] == company_id
# ---------------------------------------------------------------------------
# 5 Company Sources
# ---------------------------------------------------------------------------
class TestRegistrySources:
"""Endpoint: GET /companies/{id}/sources."""
async def test_list_sources(self, registry_client, seed_ids):
"""GET /companies/{id}/sources — AAPL has at least 1 source."""
company_id = seed_ids["companies"]["AAPL"]
resp = await registry_client.get(f"/companies/{company_id}/sources")
assert resp.status_code == 200
data = resp.json()
assert isinstance(data, list)
assert len(data) >= 1
for s in data:
assert "id" in s
assert "source_type" in s
assert "source_name" in s
assert "active" in s
# ---------------------------------------------------------------------------
# 6 Company Aliases
# ---------------------------------------------------------------------------
class TestRegistryAliases:
"""Endpoint: GET /companies/{id}/aliases."""
async def test_list_aliases(self, registry_client, seed_ids):
"""GET /companies/{id}/aliases — AAPL has at least 1 alias."""
company_id = seed_ids["companies"]["AAPL"]
resp = await registry_client.get(f"/companies/{company_id}/aliases")
assert resp.status_code == 200
data = resp.json()
assert isinstance(data, list)
assert len(data) >= 1
for a in data:
assert "id" in a
assert "alias" in a
assert "alias_type" in a
# ---------------------------------------------------------------------------
# 7 Competitors
# ---------------------------------------------------------------------------
class TestRegistryCompetitors:
"""Endpoint: GET /companies/{id}/competitors."""
async def test_list_competitors(self, registry_client, seed_ids):
"""GET /companies/{id}/competitors — AAPL has MSFT as competitor."""
company_id = seed_ids["companies"]["AAPL"]
resp = await registry_client.get(f"/companies/{company_id}/competitors")
assert resp.status_code == 200
data = resp.json()
assert isinstance(data, list)
assert len(data) >= 1
# AAPL ↔ MSFT relationship exists in seed data
msft_id = seed_ids["companies"]["MSFT"]
partner_ids = set()
for rel in data:
assert "id" in rel
assert "relationship_type" in rel
assert "strength" in rel
# The "other" company should be enriched with ticker
if rel.get("company_a_id") == company_id:
partner_ids.add(rel["company_b_id"])
else:
partner_ids.add(rel["company_a_id"])
assert msft_id in partner_ids
# ---------------------------------------------------------------------------
# 8 Exposure Profile
# ---------------------------------------------------------------------------
class TestRegistryExposure:
"""Endpoint: GET /companies/{id}/exposure."""
async def test_get_exposure(self, registry_client, seed_ids):
"""GET /companies/{id}/exposure — AAPL has an active exposure profile."""
company_id = seed_ids["companies"]["AAPL"]
resp = await registry_client.get(f"/companies/{company_id}/exposure")
assert resp.status_code == 200
data = resp.json()
assert data["company_id"] == company_id
assert data["active"] is True
assert data["market_position_tier"] == "global_leader"
assert isinstance(data["geographic_revenue_mix"], dict)
assert "North America" in data["geographic_revenue_mix"]
assert isinstance(data["supply_chain_regions"], list)
assert len(data["supply_chain_regions"]) >= 1
assert isinstance(data["key_input_commodities"], list)
assert isinstance(data["regulatory_jurisdictions"], list)
assert 0 <= data["export_dependency_pct"] <= 1
assert 0 <= data["confidence"] <= 1
assert data["version"] >= 1