/
/
/
1"""Test Tidal Playlist Manager."""
2
3from unittest.mock import AsyncMock, Mock, patch
4
5import pytest
6
7from music_assistant.providers.tidal.playlist import TidalPlaylistManager
8
9
10@pytest.fixture
11def provider_mock() -> Mock:
12 """Return a mock provider."""
13 provider = Mock()
14 provider.auth.user_id = "12345"
15 provider.api = AsyncMock()
16 provider.logger = Mock()
17 return provider
18
19
20@pytest.fixture
21def playlist_manager(provider_mock: Mock) -> TidalPlaylistManager:
22 """Return a TidalPlaylistManager instance."""
23 return TidalPlaylistManager(provider_mock)
24
25
26@patch("music_assistant.providers.tidal.playlist.parse_playlist")
27async def test_create_playlist(
28 mock_parse_playlist: Mock, playlist_manager: TidalPlaylistManager, provider_mock: Mock
29) -> None:
30 """Test create_playlist."""
31 provider_mock.api.post.return_value = {"uuid": "1", "title": "Test Playlist"}
32 mock_parse_playlist.return_value = Mock(item_id="1")
33
34 playlist = await playlist_manager.create("Test Playlist")
35
36 assert playlist.item_id == "1"
37 provider_mock.api.post.assert_called_with(
38 "users/12345/playlists",
39 data={"title": "Test Playlist", "description": ""},
40 as_form=True,
41 )
42 mock_parse_playlist.assert_called_once()
43
44
45async def test_add_playlist_tracks(
46 playlist_manager: TidalPlaylistManager, provider_mock: Mock
47) -> None:
48 """Test add_playlist_tracks."""
49 # Mock get response with ETag
50 provider_mock.api.get.return_value = ({"numberOfTracks": 5}, "etag_123")
51
52 await playlist_manager.add_tracks("1", ["track_1", "track_2"])
53
54 provider_mock.api.get.assert_called_with("playlists/1", return_etag=True)
55 provider_mock.api.post.assert_called_with(
56 "playlists/1/items",
57 data={
58 "onArtifactNotFound": "SKIP",
59 "trackIds": "track_1,track_2",
60 "toIndex": 5,
61 "onDupes": "SKIP",
62 },
63 as_form=True,
64 headers={"If-None-Match": "etag_123"},
65 )
66
67
68async def test_remove_playlist_tracks(
69 playlist_manager: TidalPlaylistManager, provider_mock: Mock
70) -> None:
71 """Test remove_playlist_tracks."""
72 # Mock get response with ETag
73 provider_mock.api.get.return_value = ({}, "etag_123")
74
75 # Positions are 1-based in MA, converted to 0-based for Tidal
76 await playlist_manager.remove_tracks("1", (1, 3))
77
78 provider_mock.api.get.assert_called_with("playlists/1", return_etag=True)
79 provider_mock.api.delete.assert_called_with(
80 "playlists/1/items/0,2",
81 headers={"If-None-Match": "etag_123"},
82 )
83