8000 Add diagnostics tests for Sonos by PeteRager · Pull Request #146040 · home-assistant/core · GitHub
[go: up one dir, main page]

Skip to content

Add diagnostics tests for Sonos #146040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions homeassistant/components/sonos/diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,11 @@ def get_contents(
value = getattr(speaker, attrib)
payload[attrib] = get_contents(value)

payload["enabled_entities"] = {
payload["enabled_entities"] = sorted(
entity_id
for entity_id, s in hass.data[DATA_SONOS].entity_id_mappings.items()
if s is speaker
}
)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorting the entities to make the list easier to read in diagnostics and also to allow the snapshot assertion to work reliably.

payload["media"] = await async_generate_media_info(hass, speaker)
payload["activity_stats"] = speaker.activity_stats.report()
payload["event_stats"] = speaker.event_stats.report()
Expand Down
8 changes: 8 additions & 0 deletions tests/components/sonos/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,22 @@ def cache_mock(
mock_soco.add_uri_to_queue = Mock(return_value=10)

mock_soco.avTransport = SonosMockService("AVTransport", ip_address)
mock_soco.avTransport.GetPositionInfo = Mock(
return_value=self.current_track_info
)
mock_soco.renderingControl = SonosMockService("RenderingControl", ip_address)
mock_soco.zoneGroupTopology = SonosMockService("ZoneGroupTopology", ip_address)
mock_soco.contentDirectory = SonosMockService("ContentDirectory", ip_address)
mock_soco.deviceProperties = SonosMockService("DeviceProperties", ip_address)
mock_soco.zone_group_state = Mock()
mock_soco.zone_group_state.processed_count = 10
mock_soco.zone_group_state.total_requests = 12

mock_soco.alarmClock = self.alarm_clock
mock_soco.get_battery_info.return_value = self.battery_info
mock_soco.all_zones = {mock_soco}
mock_soco.group.coordinator = mock_soco
mock_soco.household_id = "test_household_id"
self.mock_list[ip_address] = mock_soco
return mock_soco

Expand Down
182 changes: 182 additions & 0 deletions tests/components/sonos/snapshots/test_diagnostics.ambr
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
# serializer version: 1
# name: test_diagnostics_config_entry
dict({
'discovered': dict({
'RINCON_test': dict({
'_group_members_missing': list([
]),
'_last_activity': -1200.0,
'_last_event_cache': dict({
}),
'activity_stats': dict({
}),
'available': True,
'battery_info': dict({
'Health': 'GREEN',
'Level': 100,
'PowerSource': 'SONOS_CHARGING_RING',
'Temperature': 'NORMAL',
}),
'enabled_entities': list([
'binary_sensor.zone_a_charging',
'binary_sensor.zone_a_microphone',
'media_player.zone_a',
'number.zone_a_audio_delay',
'number.zone_a_balance',
'number.zone_a_bass',
'number.zone_a_music_surround_level',
'number.zone_a_sub_gain',
'number.zone_a_surround_level',
'number.zone_a_treble',
'sensor.zone_a_audio_input_format',
'sensor.zone_a_battery',
'switch.sonos_alarm_14',
'switch.zone_a_crossfade',
'switch.zone_a_loudness',
'switch.zone_a_night_sound',
'switch.zone_a_speech_enhancement',
'switch.zone_a_subwoofer_enabled',
'switch.zone_a_surround_enabled',
'switch.zone_a_surround_music_full_volume',
]),
'event_stats': dict({
'soco:parse_event_xml': list([
0,
0,
128,
0,
]),
}),
'hardware_version': '1.20.1.6-1.1',
'household_id': 'test_household_id',
'is_coordinator': True,
'media': dict({
'album_name': None,
'artist': None,
'channel': None,
'current_track_poll': dict({
'album': '',
'album_art': '',
'artist': '',
'duration': 'NOT_IMPLEMENTED',
'duration_in_s': None,
'metadata': 'NOT_IMPLEMENTED',
'playlist_position': '1',
'position': 'NOT_IMPLEMENTED',
'position_in_s': None,
'title': '',
'uri': '',
}),
'duration': None,
'image_url': None,
'playlist_name': None,
'queue_position': None,
'source_name': None,
'title': None,
'uri': None,
}),
'model_name': 'Model Name',
'model_number': 'S12',
'software_version': '49.2-64250',
'subscription_address': '192.168.42.2:8080',
'subscriptions_failed': False,
'version': '13.1',
'zone_group_state_stats': dict({
'processed': 10,
'total_requests': 12,
}),
'zone_name': 'Zone A',
}),
}),
'discovery_known': list([
'RINCON_test',
]),
})
# ---
# name: test_diagnostics_device
dict({
'_group_members_missing': list([
]),
'_last_activity': -1200.0,
'_last_event_cache': dict({
}),
'activity_stats': dict({
}),
'available': True,
'battery_info': dict({
'Health': 'GREEN',
'Level': 100,
'PowerSource': 'SONOS_CHARGING_RING',
'Temperature': 'NORMAL',
}),
'enabled_entities': list([
'binary_sensor.zone_a_charging',
'binary_sensor.zone_a_microphone',
'media_player.zone_a',
'number.zone_a_audio_delay',
'number.zone_a_balance',
'number.zone_a_bass',
'number.zone_a_music_surround_level',
'number.zone_a_sub_gain',
'number.zone_a_surround_level',
'number.zone_a_treble',
'sensor.zone_a_audio_input_format',
'sensor.zone_a_battery',
'switch.sonos_alarm_14',
'switch.zone_a_crossfade',
'switch.zone_a_loudness',
'switch.zone_a_night_sound',
'switch.zone_a_speech_enhancement',
'switch.zone_a_subwoofer_enabled',
'switch.zone_a_surround_enabled',
'switch.zone_a_surround_music_full_volume',
]),
'event_stats': dict({
'soco:parse_event_xml': list([
0,
0,
128,
0,
]),
}),
'hardware_version': '1.20.1.6-1.1',
'household_id': 'test_household_id',
'is_coordinator': True,
'media': dict({
'album_name': None,
'artist': None,
'channel': None,
'current_track_poll': dict({
'album': '',
'album_art': '',
'artist': '',
'duration': 'NOT_IMPLEMENTED',
'duration_in_s': None,
'metadata': 'NOT_IMPLEMENTED',
'playlist_position': '1',
'position': 'NOT_IMPLEMENTED',
'position_in_s': None,
'title': '',
'uri': '',
}),
'duration': None,
'image_url': None,
'playlist_name': None,
'queue_position': None,
'source_name': None,
'title': None,
'uri': None,
}),
'model_name': 'Model Name',
'model_number': 'S12',
'software_version': '49.2-64250',
'subscription_address': '192.168.42.2:8080',
'subscriptions_failed': False,
'version': '13.1',
'zone_group_state_stats': dict({
'processed': 10,
'total_requests': 12,
}),
'zone_name': 'Zone A',
})
# ---
63 changes: 63 additions & 0 deletions tests/components/sonos/test_diagnostics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""Tests for the diagnostics data provided by the Sonos integration."""

from syrupy.assertion import SnapshotAssertion
from syrupy.filters import paths

from homeassistant.components.sonos.const import DOMAIN
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceRegistry

from tests.common import MockConfigEntry
from tests.components.diagnostics import (
get_diagnostics_for_config_entry,
get_diagnostics_for_device,
)
from tests.typing import ClientSessionGenerator


async def test_diagnostics_config_entry(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
async_autosetup_sonos,
config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test diagnostics for config entry."""

result = await get_diagnostics_for_config_entry(hass, hass_client, config_entry)

# Exclude items that are timing dependent.
assert result == snapshot(
exclude=paths(
"current_timestamp",
"discovered.RINCON_test.event_stats.soco:from_didl_string",
"discovered.RINCON_test.sonos_group_entities",
)
)


async def test_diagnostics_device(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
6A3C device_registry: DeviceRegistry,
async_autosetup_sonos,
config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test diagnostics for device."""

TEST_DEVICE = "RINCON_test"

device_entry = device_registry.async_get_device(identifiers={(DOMAIN, TEST_DEVICE)})
assert device_entry is not None

result = await get_diagnostics_for_device(
hass, hass_client, config_entry, device_entry
)

assert result == snapshot(
exclude=paths(
"event_stats.soco:from_didl_string",
"sonos_group_entities",
)
)
0