Skip to content

Commit 61a9094

Browse files
authored
Update WLED Select Options after update (home-assistant#154205)
Co-authored-by: mik-laj <[email protected]>
1 parent d140eb4 commit 61a9094

File tree

2 files changed

+117
-16
lines changed

2 files changed

+117
-16
lines changed

homeassistant/components/wled/select.py

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,6 @@ def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
7979
super().__init__(coordinator=coordinator)
8080

8181
self._attr_unique_id = f"{coordinator.data.info.mac_address}_preset"
82-
sorted_values = sorted(
83-
coordinator.data.presets.values(), key=lambda preset: preset.name
84-
)
85-
self._attr_options = [preset.name for preset in sorted_values]
8682

8783
@property
8884
def available(self) -> bool:
@@ -100,6 +96,14 @@ def current_option(self) -> str | None:
10096
return preset.name
10197
return None
10298

99+
@property
100+
def options(self) -> list[str]:
101+
"""Return a list of selectable options."""
102+
sorted_values = sorted(
103+
self.coordinator.data.presets.values(), key=lambda preset: preset.name
104+
)
105+
return [preset.name for preset in sorted_values]
106+
103107
@wled_exception_handler
104108
async def async_select_option(self, option: str) -> None:
105109
"""Set WLED segment to the selected preset."""
@@ -116,10 +120,6 @@ def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
116120
super().__init__(coordinator=coordinator)
117121

118122
self._attr_unique_id = f"{coordinator.data.info.mac_address}_playlist"
119-
sorted_values = sorted(
120-
coordinator.data.playlists.values(), key=lambda playlist: playlist.name
121-
)
122-
self._attr_options = [playlist.name for playlist in sorted_values]
123123

124124
@property
125125
def available(self) -> bool:
@@ -137,6 +137,14 @@ def current_option(self) -> str | None:
137137
return playlist.name
138138
return None
139139

140+
@property
141+
def options(self) -> list[str]:
142+
"""Return a list of selectable options."""
143+
sorted_values = sorted(
144+
self.coordinator.data.playlists.values(), key=lambda playlist: playlist.name
145+
)
146+
return [playlist.name for playlist in sorted_values]
147+
140148
@wled_exception_handler
141149
async def async_select_option(self, option: str) -> None:
142150
"""Set WLED segment to the selected playlist."""
@@ -161,10 +169,6 @@ def __init__(self, coordinator: WLEDDataUpdateCoordinator, segment: int) -> None
161169
self._attr_translation_placeholders = {"segment": str(segment)}
162170

163171
self._attr_unique_id = f"{coordinator.data.info.mac_address}_palette_{segment}"
164-
sorted_values = sorted(
165-
coordinator.data.palettes.values(), key=lambda palette: palette.name
166-
)
167-
self._attr_options = [palette.name for palette in sorted_values]
168172
self._segment = segment
169173

170174
@property
@@ -180,9 +184,22 @@ def available(self) -> bool:
180184
@property
181185
def current_option(self) -> str | None:
182186
"""Return the current selected color palette."""
183-
return self.coordinator.data.palettes[
184-
int(self.coordinator.data.state.segments[self._segment].palette_id)
185-
].name
187+
if not self.coordinator.data.palettes:
188+
return None
189+
if (segment := self.coordinator.data.state.segments.get(self._segment)) is None:
190+
return None
191+
palette_id = int(segment.palette_id)
192+
if (palette := self.coordinator.data.palettes.get(palette_id)) is None:
193+
return None
194+
return palette.name
195+
196+
@property
197+
def options(self) -> list[str]:
198+
"""Return a list of selectable options."""
199+
sorted_values = sorted(
200+
self.coordinator.data.palettes.values(), key=lambda palette: palette.name
201+
)
202+
return [palette.name for palette in sorted_values]
186203

187204
@wled_exception_handler
188205
async def async_select_option(self, option: str) -> None:

tests/components/wled/test_select.py

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
"""Tests for the WLED select platform."""
22

3+
import typing
34
from unittest.mock import MagicMock
45

56
from freezegun.api import FrozenDateTimeFactory
67
import pytest
78
from syrupy.assertion import SnapshotAssertion
8-
from wled import Device as WLEDDevice, WLEDConnectionError, WLEDError
9+
from wled import (
10+
Device as WLEDDevice,
11+
Palette as WLEDPalette,
12+
Playlist as WLEDPlaylist,
13+
Preset as WLEDPreset,
14+
WLEDConnectionError,
15+
WLEDError,
16+
)
917

1018
from homeassistant.components.select import ATTR_OPTION, DOMAIN as SELECT_DOMAIN
1119
from homeassistant.components.wled.const import DOMAIN, SCAN_INTERVAL
@@ -168,3 +176,79 @@ async def test_playlist_unavailable_without_playlists(hass: HomeAssistant) -> No
168176
"""Test WLED playlist entity is unavailable when playlists are not available."""
169177
assert (state := hass.states.get("select.wled_rgb_light_playlist"))
170178
assert state.state == STATE_UNAVAILABLE
179+
180+
181+
PLAYLIST = {"ps": [1], "dur": [100], "transition": [7], "repeat": 0, "end": 0, "r": 0}
182+
183+
184+
@pytest.mark.parametrize(
185+
("entity_id", "data_attr", "new_data", "new_options"),
186+
[
187+
(
188+
"select.wled_rgb_light_preset",
189+
"presets",
190+
{
191+
1: WLEDPreset.from_dict({"preset_id": 1, "n": "Preset 1"}),
192+
2: WLEDPreset.from_dict({"preset_id": 2, "n": "Preset 2"}),
193+
},
194+
["Preset 1", "Preset 2"],
195+
),
196+
(
197+
"select.wled_rgb_light_playlist",
198+
"playlists",
199+
{
200+
1: WLEDPlaylist.from_dict(
201+
{"playlist_id": 1, "n": "Playlist 1", "playlist": PLAYLIST}
202+
),
203+
2: WLEDPlaylist.from_dict(
204+
{"playlist_id": 2, "n": "Playlist 2", "playlist": PLAYLIST}
205+
),
206+
},
207+
["Playlist 1", "Playlist 2"],
208+
),
209+
(
210+
"select.wled_rgb_light_color_palette",
211+
"palettes",
212+
{
213+
0: WLEDPalette.from_dict({"palette_id": 0, "name": "Palette 1"}),
214+
1: WLEDPalette.from_dict({"palette_id": 1, "name": "Palette 2"}),
215+
},
216+
["Palette 1", "Palette 2"],
217+
),
218+
],
219+
)
220+
async def test_select_load_new_options_after_update(
221+
hass: HomeAssistant,
222+
freezer: FrozenDateTimeFactory,
223+
mock_wled: MagicMock,
224+
entity_id: str,
225+
data_attr: str,
226+
new_data: typing.Any,
227+
new_options: list[str],
228+
) -> None:
229+
"""Test WLED select entity is updated when new options are added."""
230+
setattr(
231+
mock_wled.update.return_value,
232+
data_attr,
233+
{},
234+
)
235+
236+
freezer.tick(SCAN_INTERVAL)
237+
async_fire_time_changed(hass)
238+
await hass.async_block_till_done()
239+
240+
assert (state := hass.states.get(entity_id))
241+
assert state.attributes["options"] == []
242+
243+
setattr(
244+
mock_wled.update.return_value,
245+
data_attr,
246+
new_data,
247+
)
248+
249+
freezer.tick(SCAN_INTERVAL)
250+
async_fire_time_changed(hass)
251+
await hass.async_block_till_done()
252+
253+
assert (state := hass.states.get(entity_id))
254+
assert state.attributes["options"] == new_options

0 commit comments

Comments
 (0)