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:
@@ -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
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1–2 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
|
||||
Reference in New Issue
Block a user