"""Tests for the DeferredSignalQueue. Kevin's signals are mid/long-term — a signal that lands outside US market hours should be held in a Redis sorted-set and replayed at the next market open instead of dropped. """ from __future__ import annotations from datetime import datetime, timedelta, timezone from decimal import Decimal from uuid import uuid4 import fakeredis.aioredis import pytest from services.trade_executor.deferred_queue import DeferredSignalQueue from shared.schemas.trading import SignalDirection, TradeSignal def _signal(ticker: str = "NVDA") -> TradeSignal: return TradeSignal( signal_id=uuid4(), ticker=ticker, direction=SignalDirection.LONG, strength=0.85, strategy_sources=["meet_kevin:buy:0.85"], timestamp=datetime.now(timezone.utc), target_dollars=Decimal("2000"), ) @pytest.fixture async def redis(): r = fakeredis.aioredis.FakeRedis() try: yield r finally: await r.aclose() async def test_defer_then_pop_due_returns_signal(redis): q = DeferredSignalQueue(redis) s = _signal() past = datetime.now(timezone.utc) - timedelta(minutes=1) await q.defer(s, target_ts=past) due = await q.pop_due() assert len(due) == 1 popped_signal, _queued_at = due[0] assert popped_signal.ticker == "NVDA" assert popped_signal.signal_id == s.signal_id async def test_pop_due_skips_future_targets(redis): q = DeferredSignalQueue(redis) s_now = _signal("NVDA") s_future = _signal("AMD") now = datetime.now(timezone.utc) await q.defer(s_now, target_ts=now - timedelta(seconds=10)) await q.defer(s_future, target_ts=now + timedelta(hours=12)) due = await q.pop_due() assert [s.ticker for s, _ in due] == ["NVDA"] remaining = await q.size() assert remaining == 1 async def test_pop_due_is_atomic_pop(redis): """Once popped, a signal must NOT come back on the next pop.""" q = DeferredSignalQueue(redis) await q.defer(_signal(), target_ts=datetime.now(timezone.utc) - timedelta(seconds=1)) first = await q.pop_due() assert len(first) == 1 second = await q.pop_due() assert second == [] async def test_size_zero_when_empty(redis): q = DeferredSignalQueue(redis) assert await q.size() == 0 async def test_defer_preserves_signal_age(redis): """The original TradeSignal.timestamp (which the strategy uses for mention-age cutoffs) must survive the round-trip.""" q = DeferredSignalQueue(redis) orig_ts = datetime(2026, 6, 1, 15, 0, tzinfo=timezone.utc) s = TradeSignal( signal_id=uuid4(), ticker="MSFT", direction=SignalDirection.LONG, strength=0.7, strategy_sources=["meet_kevin"], timestamp=orig_ts, ) await q.defer(s, target_ts=datetime.now(timezone.utc) - timedelta(seconds=1)) [(popped, _)] = await q.pop_due() assert popped.timestamp == orig_ts