Remove internals from Sonos test_init.py (#147063)

* fix: test init

* fix: revert

* fix: revert

* fix: revert

* fix: revert

* fix: simplify
This commit is contained in:
Pete Sage 2025-06-18 03:21:21 -04:00 committed by GitHub
parent 07110e288d
commit 43d8a151ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 64 additions and 58 deletions

View File

@ -85,6 +85,15 @@ class SonosMockService:
self.subscribe = AsyncMock(return_value=SonosMockSubscribe(ip_address))
class SonosMockRenderingService(SonosMockService):
"""Mock rendering service."""
def __init__(self, return_value: dict[str, str], ip_address="192.168.42.2") -> None:
"""Initialize the instance."""
super().__init__("RenderingControl", ip_address)
self.GetVolume = Mock(return_value=30)
class SonosMockAlarmClock(SonosMockService):
"""Mock a Sonos AlarmClock Service used in callbacks."""
@ -239,7 +248,7 @@ class SoCoMockFactory:
mock_soco.avTransport.GetPositionInfo = Mock(
return_value=self.current_track_info
)
mock_soco.renderingControl = SonosMockService("RenderingControl", ip_address)
mock_soco.renderingControl = SonosMockRenderingService(ip_address)
mock_soco.zoneGroupTopology = SonosMockService("ZoneGroupTopology", ip_address)
mock_soco.contentDirectory = SonosMockService("ContentDirectory", ip_address)
mock_soco.deviceProperties = SonosMockService("DeviceProperties", ip_address)

View File

@ -3,15 +3,15 @@
import asyncio
from datetime import timedelta
import logging
from unittest.mock import Mock, patch
from unittest.mock import Mock, PropertyMock, patch
from freezegun.api import FrozenDateTimeFactory
import pytest
from homeassistant import config_entries
from homeassistant.components import sonos
from homeassistant.components.sonos import SonosDiscoveryManager
from homeassistant.components.sonos.const import (
DATA_SONOS_DISCOVERY_MANAGER,
DISCOVERY_INTERVAL,
SONOS_SPEAKER_ACTIVITY,
)
from homeassistant.components.sonos.exception import SonosUpdateError
@ -87,76 +87,73 @@ async def test_not_configuring_sonos_not_creates_entry(hass: HomeAssistant) -> N
async def test_async_poll_manual_hosts_warnings(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
soco_factory: SoCoMockFactory,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test that host warnings are not logged repeatedly."""
await async_setup_component(
hass,
sonos.DOMAIN,
{"sonos": {"media_player": {"interface_addr": "127.0.0.1"}}},
)
await hass.async_block_till_done()
manager: SonosDiscoveryManager = hass.data[DATA_SONOS_DISCOVERY_MANAGER]
manager.hosts.add("10.10.10.10")
soco = soco_factory.cache_mock(MockSoCo(), "10.10.10.1", "Bedroom")
with (
caplog.at_level(logging.DEBUG),
patch.object(manager, "_async_handle_discovery_message"),
patch(
"homeassistant.components.sonos.async_call_later"
) as mock_async_call_later,
patch("homeassistant.components.sonos.async_dispatcher_send"),
patch(
"homeassistant.components.sonos.sync_get_visible_zones",
side_effect=[
OSError(),
OSError(),
[],
[],
OSError(),
],
),
patch.object(
type(soco), "visible_zones", new_callable=PropertyMock
) as mock_visible_zones,
):
# First call fails, it should be logged as a WARNING message
mock_visible_zones.side_effect = OSError()
caplog.clear()
await manager.async_poll_manual_hosts()
assert len(caplog.messages) == 1
record = caplog.records[0]
assert record.levelname == "WARNING"
assert "Could not get visible Sonos devices from" in record.message
assert mock_async_call_later.call_count == 1
await _setup_hass(hass)
assert [
rec.levelname
for rec in caplog.records
if "Could not get visible Sonos devices from" in rec.message
] == ["WARNING"]
# Second call fails again, it should be logged as a DEBUG message
mock_visible_zones.side_effect = OSError()
caplog.clear()
await manager.async_poll_manual_hosts()
assert len(caplog.messages) == 1
record = caplog.records[0]
assert record.levelname == "DEBUG"
assert "Could not get visible Sonos devices from" in record.message
assert mock_async_call_later.call_count == 2
freezer.tick(DISCOVERY_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
assert [
rec.levelname
for rec in caplog.records
if "Could not get visible Sonos devices from" in rec.message
] == ["DEBUG"]
# Third call succeeds, it should log an info message
# Third call succeeds, logs message indicating reconnect
mock_visible_zones.return_value = {soco}
mock_visible_zones.side_effect = None
caplog.clear()
await manager.async_poll_manual_hosts()
assert len(caplog.messages) == 1
record = caplog.records[0]
assert record.levelname == "WARNING"
assert "Connection reestablished to Sonos device" in record.message
assert mock_async_call_later.call_count == 3
freezer.tick(DISCOVERY_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
assert [
rec.levelname
for rec in caplog.records
if "Connection reestablished to Sonos device" in rec.message
] == ["WARNING"]
# Fourth call succeeds again, no need to log
# Fourth call succeeds, it should log nothing
caplog.clear()
await manager.async_poll_manual_hosts()
assert len(caplog.messages) == 0
assert mock_async_call_later.call_count == 4
freezer.tick(DISCOVERY_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
assert "Connection reestablished to Sonos device" not in caplog.text
# Fifth call fail again again, should be logged as a WARNING message
# Fifth call fails again again, should be logged as a WARNING message
mock_visible_zones.side_effect = OSError()
caplog.clear()
await manager.async_poll_manual_hosts()
assert len(caplog.messages) == 1
record = caplog.records[0]
assert record.levelname == "WARNING"
assert "Could not get visible Sonos devices from" in record.message
assert mock_async_call_later.call_count == 5
freezer.tick(DISCOVERY_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert [
rec.levelname
for rec in caplog.records
if "Could not get visible Sonos devices from" in rec.message
] == ["WARNING"]
class _MockSoCoOsError(MockSoCo):