c85c0068a2
- 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
209 lines
7.7 KiB
Python
209 lines
7.7 KiB
Python
"""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
|