"""Pytest fixtures and shared setup for the WiiM integration tests.""" from collections.abc import Generator from socket import AddressFamily # pylint: disable=no-name-in-module from unittest.mock import AsyncMock, MagicMock, patch import pytest from wiim.consts import AudioOutputHwMode, InputMode, LoopMode, PlayingStatus from wiim.controller import WiimController from wiim.models import ( WiimGroupRole, WiimGroupSnapshot, WiimLoopState, WiimProbeResult, WiimQueueSnapshot, WiimRepeatMode, WiimTransportCapabilities, ) from homeassistant.components.wiim import DOMAIN from homeassistant.const import CONF_HOST from tests.common import MockConfigEntry @pytest.fixture(autouse=True) def mock_local_ip() -> Generator[AsyncMock]: """Mock the route lookup that picks the UPnP event callback address.""" with patch( "homeassistant.components.wiim.util.async_get_local_ip", return_value=(AddressFamily.AF_INET, "192.168.1.10"), ) as mock_get_local_ip: yield mock_get_local_ip @pytest.fixture def mock_setup_entry() -> Generator[AsyncMock]: """Mock setting up a config entry.""" with patch( "homeassistant.components.wiim.async_setup_entry", return_value=True ) as mock_setup: yield mock_setup @pytest.fixture def mock_config_entry() -> MockConfigEntry: """Mock Home Assistant ConfigEntry.""" return MockConfigEntry( domain=DOMAIN, data={CONF_HOST: "192.168.1.100"}, title="Test WiiM Device", unique_id="uuid:test-udn-1234", ) @pytest.fixture def mock_wiim_device() -> Generator[AsyncMock]: """Patch async_create_wiim_device and return the mocked WiimDevice instance.""" with patch( "homeassistant.components.wiim.async_create_wiim_device", autospec=True, ) as mock_create: mock = mock_create.return_value # Expose the factory so tests can assert its call kwargs. mock.create_mock = mock_create mock.udn = "uuid:test-udn-1234" mock.name = "Test WiiM Device" mock.model_name = "WiiM Pro" mock.manufacturer = "Linkplay Tech" mock.firmware_version = "4.8.523456" mock.ip_address = "192.168.1.100" mock.http_api_url = "http://192.168.1.100:8080" mock.presentation_url = "http://192.168.1.100:8080/web_interface" mock.available = True def set_available(available: bool) -> None: mock.available = available mock.set_available = MagicMock(side_effect=set_available) mock.model = "WiiM Pro" mock.volume = 50 mock.is_muted = False mock.supports_http_api = False mock.playing_status = PlayingStatus.STOPPED mock.loop_mode = LoopMode.SHUFFLE_DISABLE_REPEAT_NONE mock.loop_state = WiimLoopState( repeat=WiimRepeatMode.OFF, shuffle=False, ) mock.input_mode = InputMode.LINE_IN mock.audio_output_hw_mode = AudioOutputHwMode.SPEAKER_OUT.display_name # type: ignore[attr-defined] mock.mac_address = "AA:BB:CC:DD:EE:FF" mock.current_track_info = {} mock.current_media = None mock.current_track_duration = 0 mock.play_mode = "Network" mock.equalizer_mode = "" mock.current_position = 0 mock.next_track_uri = "" mock.event_data = {} mock.general_event_callback = None mock.av_transport_event_callback = None mock.rendering_control_event_callback = None mock.play_queue_event_callback = None mock.output_mode = "speaker" mock.supported_input_modes = (InputMode.LINE_IN.display_name,) # type: ignore[attr-defined] mock.supported_output_modes = ( AudioOutputHwMode.SPEAKER_OUT.display_name, # type: ignore[attr-defined] ) upnp_device = MagicMock() upnp_device.udn = mock.udn upnp_device.friendly_name = mock.name upnp_device.model_name = mock.model_name upnp_device.manufacturer = mock.manufacturer upnp_device.serial_number = "TESTSERIAL123" upnp_device.presentation_url = mock.presentation_url upnp_device.get_device_info = MagicMock( return_value={ "udn": mock.udn, "friendly_name": mock.name, "model_name": mock.model_name, "manufacturer": mock.manufacturer, "serial_number": upnp_device.serial_number, } ) mock.upnp_device = upnp_device mock.get_audio_output_hw_mode = AsyncMock(return_value="speaker") mock.async_get_play_queue = AsyncMock(return_value=[]) mock.async_get_audio_output_modes = AsyncMock(return_value=[]) mock.async_get_input_modes = AsyncMock(return_value=[]) mock.async_get_play_mediums = AsyncMock(return_value=[]) mock.async_get_transport_capabilities = AsyncMock( return_value=WiimTransportCapabilities( can_next=False, can_previous=False, can_repeat=False, can_shuffle=False, ) ) mock.async_get_presets = AsyncMock(return_value=()) mock.async_get_queue_snapshot = AsyncMock( return_value=WiimQueueSnapshot(items=()) ) mock.as_diagnostics = MagicMock() mock.build_loop_mode = MagicMock( return_value=LoopMode.SHUFFLE_DISABLE_REPEAT_NONE ) yield mock @pytest.fixture def mock_wiim_controller(mock_wiim_device: AsyncMock) -> Generator[MagicMock]: """Mock a WiimController instance.""" mock = MagicMock(spec=WiimController) mock.add_device = AsyncMock() mock.disconnect = AsyncMock() mock.remove_device = AsyncMock() mock.async_update_all_multiroom_status = AsyncMock() mock.get_group_snapshot.return_value = WiimGroupSnapshot( role=WiimGroupRole.STANDALONE, leader_udn=mock_wiim_device.udn, member_udns=(mock_wiim_device.udn,), ) mock.get_device.side_effect = lambda _udn: mock_wiim_device with patch( "homeassistant.components.wiim.WiimController", return_value=mock, ): yield mock @pytest.fixture def mock_probe_player() -> Generator[AsyncMock]: """Mock a WiimProbePlayer instance.""" with patch( "homeassistant.components.wiim.config_flow.async_probe_wiim_device" ) as mock_probe: mock_probe.return_value = WiimProbeResult( host="192.168.1.100", udn="uuid:test-udn-1234", name="WiiM Pro", location="http://192.168.1.100:49152/description.xml", model="WiiM Pro", ) yield mock_probe