From f33e8c518f9b71a6240fe3166d26d3349e838ea3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 26 Apr 2023 18:39:42 +0200 Subject: [PATCH] Ensure lutron_caseta logbook platform does not raise when integration is not loaded (#91978) --- .../components/lutron_caseta/logbook.py | 12 +- .../components/lutron_caseta/test_logbook.py | 134 +++++++++++++++++- 2 files changed, 141 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/lutron_caseta/logbook.py b/homeassistant/components/lutron_caseta/logbook.py index 18c46405ed0..ec612ded375 100644 --- a/homeassistant/components/lutron_caseta/logbook.py +++ b/homeassistant/components/lutron_caseta/logbook.py @@ -38,11 +38,15 @@ def async_describe_events( device_type = data[ATTR_TYPE] leap_button_number = data[ATTR_LEAP_BUTTON_NUMBER] dr_device_id = data[ATTR_DEVICE_ID] - lutron_data = get_lutron_data_by_dr_id(hass, dr_device_id) - keypad = lutron_data.keypad_data.dr_device_id_to_keypad.get(dr_device_id) - keypad_id = keypad["lutron_device_id"] + rev_button_map: dict[int, str] | None = None + keypad_button_names_to_leap: dict[int, dict[str, int]] = {} + keypad_id: int = -1 - keypad_button_names_to_leap = lutron_data.keypad_data.button_names_to_leap + if lutron_data := get_lutron_data_by_dr_id(hass, dr_device_id): + keypad_data = lutron_data.keypad_data + keypad = keypad_data.dr_device_id_to_keypad.get(dr_device_id) + keypad_id = keypad["lutron_device_id"] + keypad_button_names_to_leap = keypad_data.button_names_to_leap if not (rev_button_map := LEAP_TO_DEVICE_TYPE_SUBTYPE_MAP.get(device_type)): if fwd_button_map := keypad_button_names_to_leap.get(keypad_id): diff --git a/tests/components/lutron_caseta/test_logbook.py b/tests/components/lutron_caseta/test_logbook.py index 4f4ee08f3bc..8390370d16d 100644 --- a/tests/components/lutron_caseta/test_logbook.py +++ b/tests/components/lutron_caseta/test_logbook.py @@ -18,9 +18,10 @@ from homeassistant.components.lutron_caseta.const import ( from homeassistant.components.lutron_caseta.models import LutronCasetaData from homeassistant.const import ATTR_DEVICE_ID, CONF_HOST from homeassistant.core import HomeAssistant +from homeassistant.helpers import device_registry as dr from homeassistant.setup import async_setup_component -from . import MockBridge +from . import MockBridge, async_setup_integration from tests.common import MockConfigEntry from tests.components.logbook.common import MockRow, mock_humanify @@ -78,3 +79,134 @@ async def test_humanify_lutron_caseta_button_event(hass: HomeAssistant) -> None: assert event1["name"] == "Dining Room Pico" assert event1["domain"] == DOMAIN assert event1["message"] == "press stop" + + +async def test_humanify_lutron_caseta_button_event_integration_not_loaded( + hass: HomeAssistant, +) -> None: + """Test humanifying lutron_caseta_button_events when the integration fails to load.""" + hass.config.components.add("recorder") + assert await async_setup_component(hass, "logbook", {}) + config_entry = MockConfigEntry( + domain=DOMAIN, + data={ + CONF_HOST: "1.1.1.1", + CONF_KEYFILE: "", + CONF_CERTFILE: "", + CONF_CA_CERTS: "", + }, + unique_id="abc", + ) + config_entry.add_to_hass(hass) + + with patch( + "homeassistant.components.lutron_caseta.Smartbridge.create_tls", + return_value=MockBridge(can_connect=True), + ): + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + await hass.config_entries.async_unload(config_entry.entry_id) + await hass.async_block_till_done() + + device_registry = dr.async_get(hass) + for device in device_registry.devices.values(): + if device.config_entries == {config_entry.entry_id}: + dr_device_id = device.id + break + + assert dr_device_id is not None + (event1,) = mock_humanify( + hass, + [ + MockRow( + LUTRON_CASETA_BUTTON_EVENT, + { + ATTR_SERIAL: "68551522", + ATTR_DEVICE_ID: dr_device_id, + ATTR_TYPE: "Pico3ButtonRaiseLower", + ATTR_LEAP_BUTTON_NUMBER: 1, + ATTR_BUTTON_NUMBER: 1, + ATTR_DEVICE_NAME: "Pico", + ATTR_AREA_NAME: "Dining Room", + ATTR_ACTION: "press", + }, + ), + ], + ) + + assert event1["name"] == "Dining Room Pico" + assert event1["domain"] == DOMAIN + assert event1["message"] == "press stop" + + +async def test_humanify_lutron_caseta_button_event_ra3(hass: HomeAssistant) -> None: + """Test humanifying lutron_caseta_button_events from an RA3 hub.""" + hass.config.components.add("recorder") + assert await async_setup_component(hass, "logbook", {}) + await async_setup_integration(hass, MockBridge) + + registry = dr.async_get(hass) + keypad = registry.async_get_device( + identifiers={(DOMAIN, 66286451)}, connections=set() + ) + assert keypad + + (event1,) = mock_humanify( + hass, + [ + MockRow( + LUTRON_CASETA_BUTTON_EVENT, + { + ATTR_SERIAL: "66286451", + ATTR_DEVICE_ID: keypad.id, + ATTR_TYPE: keypad.model, + ATTR_LEAP_BUTTON_NUMBER: 3, + ATTR_BUTTON_NUMBER: 3, + ATTR_DEVICE_NAME: "Keypad", + ATTR_AREA_NAME: "Breakfast", + ATTR_ACTION: "press", + }, + ), + ], + ) + + assert event1["name"] == "Breakfast Keypad" + assert event1["domain"] == DOMAIN + assert event1["message"] == "press Kitchen Pendants" + + +async def test_humanify_lutron_caseta_button_unknown_type(hass: HomeAssistant) -> None: + """Test humanifying lutron_caseta_button_events with an unknown type.""" + hass.config.components.add("recorder") + assert await async_setup_component(hass, "logbook", {}) + await async_setup_integration(hass, MockBridge) + + registry = dr.async_get(hass) + keypad = registry.async_get_device( + identifiers={(DOMAIN, 66286451)}, connections=set() + ) + assert keypad + + (event1,) = mock_humanify( + hass, + [ + MockRow( + LUTRON_CASETA_BUTTON_EVENT, + { + ATTR_SERIAL: "66286451", + ATTR_DEVICE_ID: "removed", + ATTR_TYPE: keypad.model, + ATTR_LEAP_BUTTON_NUMBER: 3, + ATTR_BUTTON_NUMBER: 3, + ATTR_DEVICE_NAME: "Keypad", + ATTR_AREA_NAME: "Breakfast", + ATTR_ACTION: "press", + }, + ), + ], + ) + + assert event1["name"] == "Breakfast Keypad" + assert event1["domain"] == DOMAIN + assert event1["message"] == "press Error retrieving button description"