"""Tests for market sentiment module.""" import pytest from unittest.mock import AsyncMock, MagicMock from shared.sentiment import SentimentData, SentimentProvider # --- SentimentData tests --- def test_sentiment_should_buy_on_fear(): s = SentimentData(fear_greed_value=15) # Extreme fear assert s.should_buy is True def test_sentiment_should_not_buy_on_greed(): s = SentimentData(fear_greed_value=75) # Greed assert s.should_buy is False def test_sentiment_should_block_extreme_greed(): s = SentimentData(fear_greed_value=85) assert s.should_block is True def test_sentiment_should_block_very_negative_news(): s = SentimentData(news_sentiment=-0.6) assert s.should_block is True def test_sentiment_no_block_on_neutral(): s = SentimentData(fear_greed_value=50, news_sentiment=0.0) assert s.should_block is False def test_sentiment_should_buy_default_no_data(): s = SentimentData() assert s.should_buy is True assert s.should_block is False def test_sentiment_positive_news_allows_buy(): s = SentimentData(fear_greed_value=50, news_sentiment=0.3) assert s.should_buy is True def test_sentiment_outflow_bullish(): s = SentimentData(exchange_netflow=-100.0) # Outflow = bullish assert s.should_buy is True def test_sentiment_inflow_bearish(): s = SentimentData(fear_greed_value=50, exchange_netflow=100.0) # Inflow = bearish assert s.should_buy is False # --- SentimentProvider tests --- @pytest.mark.asyncio async def test_provider_fetch_fear_greed(): provider = SentimentProvider() mock_response = AsyncMock() mock_response.status = 200 mock_response.json = AsyncMock( return_value={"data": [{"value": "25", "value_classification": "Extreme Fear"}]} ) mock_response.__aenter__ = AsyncMock(return_value=mock_response) mock_response.__aexit__ = AsyncMock(return_value=False) mock_session = MagicMock() mock_session.closed = False mock_session.get = MagicMock(return_value=mock_response) mock_session.close = AsyncMock() provider._session = mock_session value, label = await provider.fetch_fear_greed() assert value == 25 assert label == "Extreme Fear" await provider.close() @pytest.mark.asyncio async def test_provider_fetch_fear_greed_failure(): provider = SentimentProvider() mock_response = AsyncMock() mock_response.status = 500 mock_response.__aenter__ = AsyncMock(return_value=mock_response) mock_response.__aexit__ = AsyncMock(return_value=False) mock_session = MagicMock() mock_session.closed = False mock_session.get = MagicMock(return_value=mock_response) mock_session.close = AsyncMock() provider._session = mock_session value, label = await provider.fetch_fear_greed() assert value is None await provider.close() @pytest.mark.asyncio async def test_provider_news_disabled_without_key(): provider = SentimentProvider(cryptopanic_api_key="") score, count = await provider.fetch_news_sentiment() assert score is None assert count == 0 @pytest.mark.asyncio async def test_provider_netflow_disabled_without_key(): provider = SentimentProvider(cryptoquant_api_key="") result = await provider.fetch_exchange_netflow() assert result is None @pytest.mark.asyncio async def test_provider_get_sentiment_aggregates(): provider = SentimentProvider() mock_response = AsyncMock() mock_response.status = 200 mock_response.json = AsyncMock( return_value={"data": [{"value": "20", "value_classification": "Extreme Fear"}]} ) mock_response.__aenter__ = AsyncMock(return_value=mock_response) mock_response.__aexit__ = AsyncMock(return_value=False) mock_session = MagicMock() mock_session.closed = False mock_session.get = MagicMock(return_value=mock_response) mock_session.close = AsyncMock() provider._session = mock_session sentiment = await provider.get_sentiment("SOL") assert sentiment.fear_greed_value == 20 assert sentiment.fear_greed_label == "Extreme Fear" assert provider.cached is sentiment await provider.close()