feat: competitive intelligence & historical pattern matching layer
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
"""Tests for exposure profile Pydantic models and endpoint logic."""
|
||||
import json
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from services.symbol_registry.exposure import (
|
||||
ExposureProfileCreate,
|
||||
ExposureProfileResponse,
|
||||
VALID_MARKET_POSITION_TIERS,
|
||||
VALID_SOURCES,
|
||||
_row_to_profile,
|
||||
)
|
||||
|
||||
|
||||
# --- ExposureProfileCreate validation ---
|
||||
|
||||
|
||||
def test_create_defaults():
|
||||
p = ExposureProfileCreate()
|
||||
assert p.geographic_revenue_mix == {}
|
||||
assert p.supply_chain_regions == []
|
||||
assert p.key_input_commodities == []
|
||||
assert p.regulatory_jurisdictions == []
|
||||
assert p.market_position_tier == "regional"
|
||||
assert p.export_dependency_pct == 0.0
|
||||
assert p.source == "manual"
|
||||
assert p.confidence == 1.0
|
||||
|
||||
|
||||
def test_create_with_full_data():
|
||||
p = ExposureProfileCreate(
|
||||
geographic_revenue_mix={"US": 0.6, "EU": 0.3, "CN": 0.1},
|
||||
supply_chain_regions=["CN", "TW", "KR"],
|
||||
key_input_commodities=["lithium", "cobalt"],
|
||||
regulatory_jurisdictions=["US", "EU"],
|
||||
market_position_tier="global_leader",
|
||||
export_dependency_pct=0.45,
|
||||
source="manual",
|
||||
confidence=0.95,
|
||||
)
|
||||
assert p.geographic_revenue_mix["US"] == 0.6
|
||||
assert len(p.supply_chain_regions) == 3
|
||||
assert p.market_position_tier == "global_leader"
|
||||
|
||||
|
||||
def test_create_all_valid_tiers():
|
||||
for tier in VALID_MARKET_POSITION_TIERS:
|
||||
p = ExposureProfileCreate(market_position_tier=tier)
|
||||
assert p.market_position_tier == tier
|
||||
|
||||
|
||||
def test_create_rejects_invalid_tier():
|
||||
with pytest.raises(ValidationError):
|
||||
ExposureProfileCreate(market_position_tier="mega_corp")
|
||||
|
||||
|
||||
def test_create_all_valid_sources():
|
||||
for src in VALID_SOURCES:
|
||||
p = ExposureProfileCreate(source=src)
|
||||
assert p.source == src
|
||||
|
||||
|
||||
def test_create_rejects_invalid_source():
|
||||
with pytest.raises(ValidationError):
|
||||
ExposureProfileCreate(source="guessed")
|
||||
|
||||
|
||||
def test_create_rejects_export_dependency_above_1():
|
||||
with pytest.raises(ValidationError):
|
||||
ExposureProfileCreate(export_dependency_pct=1.5)
|
||||
|
||||
|
||||
def test_create_rejects_export_dependency_below_0():
|
||||
with pytest.raises(ValidationError):
|
||||
ExposureProfileCreate(export_dependency_pct=-0.1)
|
||||
|
||||
|
||||
def test_create_rejects_confidence_above_1():
|
||||
with pytest.raises(ValidationError):
|
||||
ExposureProfileCreate(confidence=1.1)
|
||||
|
||||
|
||||
def test_create_rejects_confidence_below_0():
|
||||
with pytest.raises(ValidationError):
|
||||
ExposureProfileCreate(confidence=-0.5)
|
||||
|
||||
|
||||
# --- _row_to_profile helper ---
|
||||
|
||||
|
||||
def test_row_to_profile_converts_uuids():
|
||||
"""UUID fields should be converted to strings."""
|
||||
uid = uuid.uuid4()
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
class FakeRecord(dict):
|
||||
pass
|
||||
|
||||
row = FakeRecord(
|
||||
id=uid,
|
||||
company_id=uid,
|
||||
geographic_revenue_mix={"US": 0.5},
|
||||
supply_chain_regions=["US"],
|
||||
key_input_commodities=[],
|
||||
regulatory_jurisdictions=[],
|
||||
market_position_tier="regional",
|
||||
export_dependency_pct=0.0,
|
||||
source="manual",
|
||||
confidence=1.0,
|
||||
version=1,
|
||||
active=True,
|
||||
created_at=now,
|
||||
updated_at=now,
|
||||
)
|
||||
result = _row_to_profile(row)
|
||||
assert result["id"] == str(uid)
|
||||
assert result["company_id"] == str(uid)
|
||||
|
||||
|
||||
def test_row_to_profile_parses_json_string():
|
||||
"""geographic_revenue_mix stored as JSON string should be parsed."""
|
||||
uid = uuid.uuid4()
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
class FakeRecord(dict):
|
||||
pass
|
||||
|
||||
row = FakeRecord(
|
||||
id=uid,
|
||||
company_id=uid,
|
||||
geographic_revenue_mix='{"US": 0.7, "EU": 0.3}',
|
||||
supply_chain_regions=["US"],
|
||||
key_input_commodities=[],
|
||||
regulatory_jurisdictions=[],
|
||||
market_position_tier="regional",
|
||||
export_dependency_pct=0.0,
|
||||
source="manual",
|
||||
confidence=1.0,
|
||||
version=1,
|
||||
active=True,
|
||||
created_at=now,
|
||||
updated_at=now,
|
||||
)
|
||||
result = _row_to_profile(row)
|
||||
assert result["geographic_revenue_mix"] == {"US": 0.7, "EU": 0.3}
|
||||
|
||||
|
||||
# --- ExposureProfileResponse model ---
|
||||
|
||||
|
||||
def test_response_model_accepts_valid_data():
|
||||
now = datetime.now(timezone.utc)
|
||||
resp = ExposureProfileResponse(
|
||||
id=str(uuid.uuid4()),
|
||||
company_id=str(uuid.uuid4()),
|
||||
geographic_revenue_mix={"US": 0.5, "EU": 0.5},
|
||||
supply_chain_regions=["CN"],
|
||||
key_input_commodities=["oil"],
|
||||
regulatory_jurisdictions=["US"],
|
||||
market_position_tier="multinational",
|
||||
export_dependency_pct=0.3,
|
||||
source="inferred",
|
||||
confidence=0.8,
|
||||
version=3,
|
||||
active=True,
|
||||
created_at=now,
|
||||
updated_at=now,
|
||||
)
|
||||
assert resp.version == 3
|
||||
assert resp.source == "inferred"
|
||||
Reference in New Issue
Block a user