"""Tests for dashboard service.""" from datetime import UTC, datetime from unittest.mock import AsyncMock, Mock, patch import pytest from app.services.dashboard import DashboardService @pytest.fixture def mock_sound_repository(): """Mock sound repository.""" return Mock() @pytest.fixture def dashboard_service(mock_sound_repository): """Dashboard service with mocked dependencies.""" return DashboardService(sound_repository=mock_sound_repository) class TestDashboardService: """Test dashboard service.""" @pytest.mark.asyncio async def test_init(self, mock_sound_repository): """Test dashboard service initialization.""" service = DashboardService(sound_repository=mock_sound_repository) assert service.sound_repository == mock_sound_repository @pytest.mark.asyncio async def test_get_soundboard_statistics_success( self, dashboard_service, mock_sound_repository, ): """Test getting soundboard statistics successfully.""" # Mock repository response mock_stats = { "count": 25, "total_plays": 150, "total_duration": 75000, "total_size": 1024000, } mock_sound_repository.get_soundboard_statistics = AsyncMock( return_value=mock_stats, ) result = await dashboard_service.get_soundboard_statistics() assert result == { "sound_count": 25, "total_play_count": 150, "total_duration": 75000, "total_size": 1024000, } mock_sound_repository.get_soundboard_statistics.assert_called_once() @pytest.mark.asyncio async def test_get_soundboard_statistics_exception( self, dashboard_service, mock_sound_repository, ): """Test getting soundboard statistics with exception.""" mock_sound_repository.get_soundboard_statistics = AsyncMock( side_effect=Exception("Database error"), ) with pytest.raises(Exception, match="Database error"): await dashboard_service.get_soundboard_statistics() mock_sound_repository.get_soundboard_statistics.assert_called_once() @pytest.mark.asyncio async def test_get_track_statistics_success( self, dashboard_service, mock_sound_repository, ): """Test getting track statistics successfully.""" # Mock repository response mock_stats = { "count": 15, "total_plays": 80, "total_duration": 45000, "total_size": 512000, } mock_sound_repository.get_track_statistics = AsyncMock(return_value=mock_stats) result = await dashboard_service.get_track_statistics() assert result == { "track_count": 15, "total_play_count": 80, "total_duration": 45000, "total_size": 512000, } mock_sound_repository.get_track_statistics.assert_called_once() @pytest.mark.asyncio async def test_get_track_statistics_exception( self, dashboard_service, mock_sound_repository, ): """Test getting track statistics with exception.""" mock_sound_repository.get_track_statistics = AsyncMock( side_effect=Exception("Database error"), ) with pytest.raises(Exception, match="Database error"): await dashboard_service.get_track_statistics() mock_sound_repository.get_track_statistics.assert_called_once() @pytest.mark.asyncio async def test_get_top_sounds_success_all_time( self, dashboard_service, mock_sound_repository, ): """Test getting top sounds for all time successfully.""" # Mock repository response mock_sounds = [ { "id": 1, "name": "Sound 1", "type": "SDB", "play_count": 100, "duration": 5000, "created_at": datetime(2023, 1, 1, 12, 0, 0, tzinfo=UTC), }, { "id": 2, "name": "Sound 2", "type": "SDB", "play_count": 50, "duration": 3000, "created_at": None, }, ] mock_sound_repository.get_top_sounds = AsyncMock(return_value=mock_sounds) result = await dashboard_service.get_top_sounds("SDB", "all_time", 10) assert len(result) == 2 assert result[0] == { "id": 1, "name": "Sound 1", "type": "SDB", "play_count": 100, "duration": 5000, "created_at": "2023-01-01T12:00:00+00:00", } assert result[1] == { "id": 2, "name": "Sound 2", "type": "SDB", "play_count": 50, "duration": 3000, "created_at": None, } mock_sound_repository.get_top_sounds.assert_called_once_with( sound_type="SDB", date_filter=None, limit=10, ) @pytest.mark.asyncio async def test_get_top_sounds_success_with_period( self, dashboard_service, mock_sound_repository, ): """Test getting top sounds with specific period.""" mock_sounds = [] mock_sound_repository.get_top_sounds = AsyncMock(return_value=mock_sounds) with patch.object(dashboard_service, "_get_date_filter") as mock_date_filter: mock_date_filter.return_value = datetime(2023, 1, 1, tzinfo=UTC) result = await dashboard_service.get_top_sounds("EXT", "1_week", 5) assert result == [] mock_date_filter.assert_called_once_with("1_week") mock_sound_repository.get_top_sounds.assert_called_once_with( sound_type="EXT", date_filter=datetime(2023, 1, 1, tzinfo=UTC), limit=5, ) @pytest.mark.asyncio async def test_get_top_sounds_exception( self, dashboard_service, mock_sound_repository, ): """Test getting top sounds with exception.""" mock_sound_repository.get_top_sounds = AsyncMock( side_effect=Exception("Database error"), ) with pytest.raises(Exception, match="Database error"): await dashboard_service.get_top_sounds("SDB", "all_time", 10) mock_sound_repository.get_top_sounds.assert_called_once() def test_get_date_filter_today(self, dashboard_service): """Test date filter for today.""" with patch("app.services.dashboard.datetime") as mock_datetime: mock_now = datetime(2023, 6, 15, 14, 30, 45, 123456, tzinfo=UTC) mock_datetime.now.return_value = mock_now mock_datetime.UTC = UTC result = dashboard_service._get_date_filter("today") expected = datetime(2023, 6, 15, 0, 0, 0, 0, tzinfo=UTC) assert result == expected def test_get_date_filter_1_day(self, dashboard_service): """Test date filter for 1 day.""" with patch("app.services.dashboard.datetime") as mock_datetime: mock_now = datetime(2023, 6, 15, 14, 30, 45, tzinfo=UTC) mock_datetime.now.return_value = mock_now mock_datetime.UTC = UTC result = dashboard_service._get_date_filter("1_day") expected = datetime(2023, 6, 14, 14, 30, 45, tzinfo=UTC) assert result == expected def test_get_date_filter_1_week(self, dashboard_service): """Test date filter for 1 week.""" with patch("app.services.dashboard.datetime") as mock_datetime: mock_now = datetime(2023, 6, 15, 14, 30, 45, tzinfo=UTC) mock_datetime.now.return_value = mock_now mock_datetime.UTC = UTC result = dashboard_service._get_date_filter("1_week") expected = datetime(2023, 6, 8, 14, 30, 45, tzinfo=UTC) assert result == expected def test_get_date_filter_1_month(self, dashboard_service): """Test date filter for 1 month.""" with patch("app.services.dashboard.datetime") as mock_datetime: mock_now = datetime(2023, 6, 15, 14, 30, 45, tzinfo=UTC) mock_datetime.now.return_value = mock_now mock_datetime.UTC = UTC result = dashboard_service._get_date_filter("1_month") expected = datetime(2023, 5, 16, 14, 30, 45, tzinfo=UTC) assert result == expected def test_get_date_filter_1_year(self, dashboard_service): """Test date filter for 1 year.""" with patch("app.services.dashboard.datetime") as mock_datetime: mock_now = datetime(2023, 6, 15, 14, 30, 45, tzinfo=UTC) mock_datetime.now.return_value = mock_now mock_datetime.UTC = UTC result = dashboard_service._get_date_filter("1_year") expected = datetime(2022, 6, 15, 14, 30, 45, tzinfo=UTC) assert result == expected def test_get_date_filter_all_time(self, dashboard_service): """Test date filter for all time.""" result = dashboard_service._get_date_filter("all_time") assert result is None def test_get_date_filter_unknown_period(self, dashboard_service): """Test date filter for unknown period.""" result = dashboard_service._get_date_filter("unknown_period") assert result is None