"""Tests for fetch_playlist_ids function.""" from unittest.mock import MagicMock, patch from playlist.queries.fetch_queries import fetch_playlist_ids class TestFetchPlaylistIds: """Tests for fetch_playlist_ids function.""" @patch("playlist.queries.fetch_queries.PlaylistIdsQuery") @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_non_priority_playlists_enabled" ) @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_hourly_playlists_enabled" ) def test_fetch_playlist_ids_without_hourly_flag( self, mock_hourly_flag, mock_non_priority_flag, mock_query_class ): """Test fetch_playlist_ids calls query with include_hourly=False when flag is off.""" mock_hourly_flag.return_value = False mock_non_priority_flag.return_value = False mock_query_instance = MagicMock() mock_cursor = MagicMock() mock_cursor.fetchall.return_value = [ {"store_playlist_id": "pl.123", "store_id": "1"}, {"store_playlist_id": "pl.456", "store_id": "286"}, ] mock_query_instance.execute.return_value = mock_cursor mock_query_class.return_value = mock_query_instance result = fetch_playlist_ids() mock_hourly_flag.assert_called_once() mock_non_priority_flag.assert_called_once() mock_query_class.assert_called_once_with( include_hourly=False, include_non_priority=False, store_ids=None ) mock_query_instance.execute.assert_called_once() assert len(result) == 2 @patch("playlist.queries.fetch_queries.PlaylistIdsQuery") @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_non_priority_playlists_enabled" ) @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_hourly_playlists_enabled" ) def test_fetch_playlist_ids_with_hourly_flag( self, mock_hourly_flag, mock_non_priority_flag, mock_query_class ): """Test fetch_playlist_ids calls query with include_hourly=True when flag is on.""" mock_hourly_flag.return_value = True mock_non_priority_flag.return_value = False mock_query_instance = MagicMock() mock_cursor = MagicMock() mock_cursor.fetchall.return_value = [ {"store_playlist_id": "pl.123", "store_id": "1"}, {"store_playlist_id": "pl.456", "store_id": "286"}, {"store_playlist_id": "pl.789", "store_id": "1"}, ] mock_query_instance.execute.return_value = mock_cursor mock_query_class.return_value = mock_query_instance result = fetch_playlist_ids() mock_hourly_flag.assert_called_once() mock_non_priority_flag.assert_called_once() mock_query_class.assert_called_once_with( include_hourly=True, include_non_priority=False, store_ids=None ) mock_query_instance.execute.assert_called_once() assert len(result) == 3 @patch("playlist.queries.fetch_queries.PlaylistIdsQuery") @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_non_priority_playlists_enabled" ) @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_hourly_playlists_enabled" ) def test_fetch_playlist_ids_explicit_include_hourly_true( self, mock_hourly_flag, mock_non_priority_flag, mock_query_class ): """Test fetch_playlist_ids with explicit include_hourly=True parameter.""" mock_non_priority_flag.return_value = False mock_query_instance = MagicMock() mock_cursor = MagicMock() mock_cursor.fetchall.return_value = [ {"store_playlist_id": "pl.123", "store_id": "1"}, {"store_playlist_id": "pl.456", "store_id": "286"}, ] mock_query_instance.execute.return_value = mock_cursor mock_query_class.return_value = mock_query_instance result = fetch_playlist_ids(include_hourly=True) # Hourly flag should NOT be called when explicit parameter is provided mock_hourly_flag.assert_not_called() # Non-priority flag should still be called since no explicit parameter mock_non_priority_flag.assert_called_once() mock_query_class.assert_called_once_with( include_hourly=True, include_non_priority=False, store_ids=None ) mock_query_instance.execute.assert_called_once() assert len(result) == 2 @patch("playlist.queries.fetch_queries.PlaylistIdsQuery") @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_non_priority_playlists_enabled" ) @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_hourly_playlists_enabled" ) def test_fetch_playlist_ids_explicit_include_hourly_false( self, mock_hourly_flag, mock_non_priority_flag, mock_query_class ): """Test fetch_playlist_ids with explicit include_hourly=False parameter.""" mock_non_priority_flag.return_value = False mock_query_instance = MagicMock() mock_cursor = MagicMock() mock_cursor.fetchall.return_value = [ {"store_playlist_id": "pl.123", "store_id": "1"}, ] mock_query_instance.execute.return_value = mock_cursor mock_query_class.return_value = mock_query_instance result = fetch_playlist_ids(include_hourly=False) # Hourly flag should NOT be called when explicit parameter is provided mock_hourly_flag.assert_not_called() # Non-priority flag should still be called since no explicit parameter mock_non_priority_flag.assert_called_once() mock_query_class.assert_called_once_with( include_hourly=False, include_non_priority=False, store_ids=None ) mock_query_instance.execute.assert_called_once() assert len(result) == 1 @patch("playlist.queries.fetch_queries.PlaylistIdsQuery") def test_fetch_playlist_ids_filters_apple_music_when_disabled( self, mock_query_class ): """Test that Apple Music playlists are filtered when include_apple_music=False.""" mock_query_instance = MagicMock() mock_cursor = MagicMock() mock_cursor.fetchall.return_value = [ {"store_playlist_id": "pl.123", "store_id": 1}, # Apple Music {"store_playlist_id": "pl.456", "store_id": 286}, # Spotify {"store_playlist_id": "pl.789", "store_id": 1}, # Apple Music ] mock_query_instance.execute.return_value = mock_cursor mock_query_class.return_value = mock_query_instance result = fetch_playlist_ids( include_hourly=False, include_non_priority=False, include_apple_music=False, ) mock_query_class.assert_called_once_with( include_hourly=False, include_non_priority=False, store_ids=None ) # Should only return Spotify playlist (store_id != 1) assert len(result) == 1 assert result[0]["store_id"] == 286 assert result[0]["store_playlist_id"] == "pl.456" @patch("playlist.queries.fetch_queries.PlaylistIdsQuery") def test_fetch_playlist_ids_includes_apple_music_when_enabled( self, mock_query_class ): """Test that Apple Music playlists are included when include_apple_music=True.""" mock_query_instance = MagicMock() mock_cursor = MagicMock() mock_cursor.fetchall.return_value = [ {"store_playlist_id": "pl.123", "store_id": 1}, # Apple Music {"store_playlist_id": "pl.456", "store_id": 286}, # Spotify {"store_playlist_id": "pl.789", "store_id": 1}, # Apple Music ] mock_query_instance.execute.return_value = mock_cursor mock_query_class.return_value = mock_query_instance result = fetch_playlist_ids( include_hourly=False, include_non_priority=False, include_apple_music=True, ) mock_query_class.assert_called_once_with( include_hourly=False, include_non_priority=False, store_ids=None ) # Should return all playlists including Apple Music assert len(result) == 3 assert result[0]["store_id"] == 1 assert result[1]["store_id"] == 286 assert result[2]["store_id"] == 1 @patch("playlist.queries.fetch_queries.PlaylistIdsQuery") def test_fetch_playlist_ids_default_includes_apple_music(self, mock_query_class): """Test that Apple Music playlists are included by default (backward compatibility).""" mock_query_instance = MagicMock() mock_cursor = MagicMock() mock_cursor.fetchall.return_value = [ {"store_playlist_id": "pl.123", "store_id": 1}, # Apple Music {"store_playlist_id": "pl.456", "store_id": 286}, # Spotify ] mock_query_instance.execute.return_value = mock_cursor mock_query_class.return_value = mock_query_instance # Call without include_apple_music parameter (should default to True) result = fetch_playlist_ids(include_hourly=False, include_non_priority=False) mock_query_class.assert_called_once_with( include_hourly=False, include_non_priority=False, store_ids=None ) # Should return all playlists including Apple Music assert len(result) == 2 assert any(p["store_id"] == 1 for p in result) @patch("playlist.queries.fetch_queries.PlaylistIdsQuery") @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_non_priority_playlists_enabled" ) @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_hourly_playlists_enabled" ) def test_fetch_playlist_ids_with_non_priority_flag( self, mock_hourly_flag, mock_non_priority_flag, mock_query_class ): """Test fetch_playlist_ids calls query with include_non_priority=True when flag is on.""" mock_hourly_flag.return_value = False mock_non_priority_flag.return_value = True mock_query_instance = MagicMock() mock_cursor = MagicMock() mock_cursor.fetchall.return_value = [ {"store_playlist_id": "pl.123", "store_id": "286"}, {"store_playlist_id": "pl.456", "store_id": "286"}, {"store_playlist_id": "pl.789", "store_id": "286"}, ] mock_query_instance.execute.return_value = mock_cursor mock_query_class.return_value = mock_query_instance result = fetch_playlist_ids() mock_hourly_flag.assert_called_once() mock_non_priority_flag.assert_called_once() mock_query_class.assert_called_once_with( include_hourly=False, include_non_priority=True, store_ids=None ) mock_query_instance.execute.assert_called_once() assert len(result) == 3 @patch("playlist.queries.fetch_queries.PlaylistIdsQuery") @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_hourly_playlists_enabled" ) def test_fetch_playlist_ids_explicit_include_non_priority_true( self, mock_hourly_flag, mock_query_class ): """Test fetch_playlist_ids with explicit include_non_priority=True parameter.""" mock_hourly_flag.return_value = False mock_query_instance = MagicMock() mock_cursor = MagicMock() mock_cursor.fetchall.return_value = [ {"store_playlist_id": "pl.123", "store_id": "286"}, {"store_playlist_id": "pl.456", "store_id": "286"}, ] mock_query_instance.execute.return_value = mock_cursor mock_query_class.return_value = mock_query_instance result = fetch_playlist_ids(include_non_priority=True) # Hourly flag should still be called since no explicit parameter mock_hourly_flag.assert_called_once() mock_query_class.assert_called_once_with( include_hourly=False, include_non_priority=True, store_ids=None ) mock_query_instance.execute.assert_called_once() assert len(result) == 2 @patch("playlist.queries.fetch_queries.PlaylistIdsQuery") @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_hourly_playlists_enabled" ) def test_fetch_playlist_ids_explicit_include_non_priority_false( self, mock_hourly_flag, mock_query_class ): """Test fetch_playlist_ids with explicit include_non_priority=False parameter.""" mock_hourly_flag.return_value = False mock_query_instance = MagicMock() mock_cursor = MagicMock() mock_cursor.fetchall.return_value = [ {"store_playlist_id": "pl.123", "store_id": "1"}, ] mock_query_instance.execute.return_value = mock_cursor mock_query_class.return_value = mock_query_instance result = fetch_playlist_ids(include_non_priority=False) # Hourly flag should still be called since no explicit parameter mock_hourly_flag.assert_called_once() mock_query_class.assert_called_once_with( include_hourly=False, include_non_priority=False, store_ids=None ) mock_query_instance.execute.assert_called_once() assert len(result) == 1 @patch("playlist.queries.fetch_queries.PlaylistIdsQuery") @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_non_priority_playlists_enabled" ) @patch( "playlist.queries.fetch_queries.is_insights_playlist_page_hourly_playlists_enabled" ) def test_fetch_playlist_ids_both_flags_enabled( self, mock_hourly_flag, mock_non_priority_flag, mock_query_class ): """Test fetch_playlist_ids with both hourly and non_priority flags enabled.""" mock_hourly_flag.return_value = True mock_non_priority_flag.return_value = True mock_query_instance = MagicMock() mock_cursor = MagicMock() mock_cursor.fetchall.return_value = [ {"store_playlist_id": "pl.123", "store_id": "1"}, {"store_playlist_id": "pl.456", "store_id": "286"}, {"store_playlist_id": "pl.789", "store_id": "286"}, ] mock_query_instance.execute.return_value = mock_cursor mock_query_class.return_value = mock_query_instance result = fetch_playlist_ids() mock_hourly_flag.assert_called_once() mock_non_priority_flag.assert_called_once() mock_query_class.assert_called_once_with( include_hourly=True, include_non_priority=True, store_ids=None ) mock_query_instance.execute.assert_called_once() assert len(result) == 3 @patch("playlist.queries.fetch_queries.PlaylistIdsQuery") def test_fetch_playlist_ids_explicit_both_parameters(self, mock_query_class): """Test fetch_playlist_ids with both explicit include_hourly and include_non_priority.""" mock_query_instance = MagicMock() mock_cursor = MagicMock() mock_cursor.fetchall.return_value = [ {"store_playlist_id": "pl.123", "store_id": "1"}, {"store_playlist_id": "pl.456", "store_id": "286"}, ] mock_query_instance.execute.return_value = mock_cursor mock_query_class.return_value = mock_query_instance result = fetch_playlist_ids(include_hourly=True, include_non_priority=True) # No feature flags should be called when explicit parameters are provided mock_query_class.assert_called_once_with( include_hourly=True, include_non_priority=True, store_ids=None ) mock_query_instance.execute.assert_called_once() assert len(result) == 2