diff --git a/homeassistant/components/home_connect/select.py b/homeassistant/components/home_connect/select.py index 7d8b315b657..025480828d8 100644 --- a/homeassistant/components/home_connect/select.py +++ b/homeassistant/components/home_connect/select.py @@ -11,7 +11,7 @@ from aiohomeconnect.model.error import HomeConnectError from aiohomeconnect.model.program import Execution from homeassistant.components.select import SelectEntity, SelectEntityDescription -from homeassistant.core import HomeAssistant +from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback @@ -366,16 +366,37 @@ class HomeConnectProgramSelectEntity(HomeConnectEntity, SelectEntity): appliance, desc, ) + self.set_options() + + def set_options(self) -> None: + """Set the options for the entity.""" self._attr_options = [ PROGRAMS_TRANSLATION_KEYS_MAP[program.key] - for program in appliance.programs + for program in self.appliance.programs if program.key != ProgramKey.UNKNOWN and ( program.constraints is None - or program.constraints.execution in desc.allowed_executions + or program.constraints.execution + in self.entity_description.allowed_executions ) ] + @callback + def refresh_options(self) -> None: + """Refresh the options for the entity.""" + self.set_options() + self.async_write_ha_state() + + async def async_added_to_hass(self) -> None: + """When entity is added to hass.""" + await super().async_added_to_hass() + self.async_on_remove( + self.coordinator.async_add_listener( + self.refresh_options, + (self.appliance.info.ha_id, EventKey.BSH_COMMON_APPLIANCE_CONNECTED), + ) + ) + def update_native_value(self) -> None: """Set the program value.""" event = self.appliance.events.get(cast(EventKey, self.bsh_key)) diff --git a/tests/components/home_connect/test_select.py b/tests/components/home_connect/test_select.py index 4f3f804eb06..6d8c090571e 100644 --- a/tests/components/home_connect/test_select.py +++ b/tests/components/home_connect/test_select.py @@ -486,6 +486,59 @@ async def test_select_exception_handling( assert getattr(client_with_exception, mock_attr).call_count == 2 +@pytest.mark.parametrize("appliance", ["Washer"], indirect=True) +async def test_programs_updated_on_connect( + appliance: HomeAppliance, + hass: HomeAssistant, + config_entry: MockConfigEntry, + integration_setup: Callable[[MagicMock], Awaitable[bool]], + setup_credentials: None, + client: MagicMock, +) -> None: + """Test that devices reconnected. + + Specifically those devices whose settings, status, etc. could + not be obtained while disconnected and once connected, the entities are added. + """ + get_all_programs_mock = client.get_all_programs + + returned_programs = ( + await get_all_programs_mock.side_effect(appliance.ha_id) + ).programs + assert len(returned_programs) > 1 + + async def get_all_programs_side_effect(ha_id: str): + if ha_id == appliance.ha_id: + return ArrayOfPrograms(returned_programs[:1]) + return await get_all_programs_mock.side_effect(ha_id) + + client.get_all_programs = AsyncMock(side_effect=get_all_programs_side_effect) + assert config_entry.state == ConfigEntryState.NOT_LOADED + assert await integration_setup(client) + assert config_entry.state == ConfigEntryState.LOADED + client.get_all_programs = get_all_programs_mock + + state = hass.states.get("select.washer_active_program") + assert state + programs = state.attributes[ATTR_OPTIONS] + + await client.add_events( + [ + EventMessage( + appliance.ha_id, + EventType.CONNECTED, + data=ArrayOfEvents([]), + ) + ] + ) + await hass.async_block_till_done() + + state = hass.states.get("select.washer_active_program") + assert state + assert state.attributes[ATTR_OPTIONS] != programs + assert len(state.attributes[ATTR_OPTIONS]) > len(programs) + + @pytest.mark.parametrize("appliance", ["Hood"], indirect=True) @pytest.mark.parametrize( (