"""Integration test: event → label generation pipeline (real Oracle + DB).""" from __future__ import annotations import datetime as dt from unittest.mock import AsyncMock, MagicMock import pytest pytestmark = pytest.mark.integration @pytest.fixture def mock_event() -> MagicMock: event = MagicMock() event.event_id = "EVT::sec::ISSUER::0000320193::2026-01-29::earnings_release::0" event.event_date = dt.date(2026, 1, 29) event.filing_time_bucket = "post_market" event.symbol_id = "SYM::AAPL::NASDAQ" event.status = "valid" return event @pytest.fixture def mock_price_bars() -> list[MagicMock]: bars = [] for i in range(8): bar = MagicMock() date = dt.date(2026, 1, 30) + dt.timedelta(days=i) bar.model_dump.return_value = { "date": date.isoformat(), "open": 220.0 + i * 0.5, "high": 225.0 + i * 0.5, "low": 218.0, "close": 222.0 + i * 0.5, "volume": 1000000, } bars.append(bar) return bars @pytest.mark.asyncio async def test_label_pipeline_end_to_end(mock_event: MagicMock, mock_price_bars: list) -> None: """Test full label generation: event → reaction_date → entry → labels.""" from libs.labeler.label_generator import LABEL_VERSION, generate_labels from libs.labeler.reaction_date import compute_reaction_date # Verify reaction_date logic reaction_date = compute_reaction_date(mock_event.event_date, mock_event.filing_time_bucket) assert reaction_date > mock_event.event_date # post_market → next day # Setup mock price service mock_price_resp = MagicMock() mock_price_resp.bars = mock_price_bars mock_price_svc = AsyncMock() mock_price_svc.get_daily_bars = AsyncMock(return_value=mock_price_resp) mock_session = AsyncMock() label = await generate_labels( session=mock_session, event=mock_event, price_svc=mock_price_svc, ticker="AAPL", ) assert label is not None assert label.event_id == mock_event.event_id assert label.label_version == LABEL_VERSION assert label.label_status in ("ok", "truncated") assert label.reaction_date == reaction_date assert label.entry_price is not None @pytest.mark.asyncio async def test_label_pipeline_handles_missing_price_data(mock_event: MagicMock) -> None: """Label pipeline handles Oracle price unavailability gracefully.""" from libs.labeler.label_generator import generate_labels mock_price_svc = AsyncMock() mock_price_svc.get_daily_bars = AsyncMock( side_effect=Exception("Oracle connection refused") ) mock_session = AsyncMock() label = await generate_labels( session=mock_session, event=mock_event, price_svc=mock_price_svc, ticker="AAPL", ) assert label.label_status == "unavailable" assert label.event_id == mock_event.event_id