/
/
/
1"""Tests for MilkDrop visualizer target resolution."""
2
3from __future__ import annotations
4
5from unittest.mock import Mock
6
7from music_assistant_models.enums import PlaybackState
8
9from music_assistant.providers.milkdrop_visualizer.relay import MilkdropRelay
10
11
12def _relay(players: list[Mock], queues: dict[str, Mock] | None = None) -> MilkdropRelay:
13 """Return a relay whose mass exposes the given players and their active queues."""
14 provider = Mock()
15 provider.mass.players.__iter__ = lambda _self: iter(players)
16 provider.mass.players.get_player = Mock(
17 side_effect={player.player_id: player for player in players}.get
18 )
19 provider.mass.player_queues.get_active_queue = Mock(side_effect=(queues or {}).get)
20 provider.logger.getChild.return_value = Mock()
21 return MilkdropRelay(provider)
22
23
24def _player(player_id: str) -> Mock:
25 """Build a player-shaped mock."""
26 player = Mock()
27 player.player_id = player_id
28 player.display_name = player_id
29 return player
30
31
32def _queue(playing: bool) -> Mock:
33 """Build a queue-shaped mock in the given playback state."""
34 queue = Mock()
35 queue.state = PlaybackState.PLAYING if playing else PlaybackState.IDLE
36 return queue
37
38
39def test_resolves_the_named_player() -> None:
40 """Any player id resolves to that player, whatever protocol it plays over."""
41 chromecast = _player("chromecast-kitchen")
42 relay = _relay([_player("dlna_box"), chromecast])
43 assert relay._resolve_target("chromecast-kitchen") is chromecast
44
45
46def test_unknown_player_resolves_to_none() -> None:
47 """A query naming no player at all is reported back rather than guessed at."""
48 relay = _relay([_player("dlna_box")])
49 assert relay._resolve_target("gone-away") is None
50
51
52def test_no_query_auto_picks_a_playing_player() -> None:
53 """With no query, a player that is playing wins over an idle one."""
54 idle = _player("dlna_box")
55 playing = _player("chromecast-kitchen")
56 relay = _relay(
57 [idle, playing],
58 {"dlna_box": _queue(playing=False), "chromecast-kitchen": _queue(playing=True)},
59 )
60 assert relay._resolve_target(None) is playing
61
62
63def test_no_query_and_nothing_playing_resolves_to_none() -> None:
64 """With nothing playing there is no audio to pick up, so no target."""
65 relay = _relay([_player("dlna_box")], {"dlna_box": _queue(playing=False)})
66 assert relay._resolve_target(None) is None
67