"""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