From db008d1d0e1a5613812594dcc32baeb66e1a5f1b Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Sun, 27 Sep 2026 20:26:58 +0200 Subject: [PATCH] Only import MQTT in Fully Kiosk once it is set up (#183289) Co-authored-by: Claude --- .../components/fully_kiosk/entity.py | 15 ++++++++++++--- tests/components/fully_kiosk/test_switch.py | 19 ++++++++++++++++++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/fully_kiosk/entity.py b/homeassistant/components/fully_kiosk/entity.py index 6f79ce005f8e..c725c39b4b5b 100644 --- a/homeassistant/components/fully_kiosk/entity.py +++ b/homeassistant/components/fully_kiosk/entity.py @@ -1,10 +1,10 @@ """Base entity for the Fully Kiosk Browser integration.""" import json +from typing import TYPE_CHECKING from yarl import URL -from homeassistant.components import mqtt from homeassistant.const import ATTR_CONNECTIONS from homeassistant.core import CALLBACK_TYPE, callback from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo @@ -14,6 +14,9 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import DOMAIN from .coordinator import FullyKioskDataUpdateCoordinator +if TYPE_CHECKING: + from homeassistant.components.mqtt import ReceiveMessage + def valid_global_mac_address(mac: str | None) -> bool: """Check if a MAC address is valid, non-locally administered address.""" @@ -65,15 +68,21 @@ class FullyKioskEntity(CoordinatorEntity[FullyKioskDataUpdateCoordinator], Entit ) -> CALLBACK_TYPE | None: """Subscribe to MQTT for a given event.""" data = self.coordinator.data + # MQTT is only imported once it is set up, as it is heavy to load if ( event is None - or not mqtt.mqtt_config_entry_enabled(self.hass) + or "mqtt" not in self.hass.config.components or not data["settings"]["mqttEnabled"] ): return None + from homeassistant.components import mqtt # noqa: PLC0415 + + if not mqtt.mqtt_config_entry_enabled(self.hass): + return None + @callback - def message_callback(message: mqtt.ReceiveMessage) -> None: + def message_callback(message: ReceiveMessage) -> None: payload = json.loads(message.payload) if "event" in payload and payload["event"] == event: event_callback(**payload) diff --git a/tests/components/fully_kiosk/test_switch.py b/tests/components/fully_kiosk/test_switch.py index 14a464e0dcd7..bcc8447a7c12 100644 --- a/tests/components/fully_kiosk/test_switch.py +++ b/tests/components/fully_kiosk/test_switch.py @@ -1,6 +1,8 @@ """Test the Fully Kiosk Browser switches.""" -from unittest.mock import MagicMock +from unittest.mock import MagicMock, patch + +import pytest from homeassistant.components import switch from homeassistant.components.fully_kiosk.const import DOMAIN @@ -141,6 +143,21 @@ async def test_switches_mqtt_update( assert entity.state == "on" +@pytest.mark.usefixtures("mock_fully_kiosk") +async def test_switches_mqtt_config_entry_not_enabled( + hass: HomeAssistant, mock_config_entry: MockConfigEntry +) -> None: + """Test no MQTT subscriptions are made without an enabled MQTT config entry.""" + hass.config.components.add("mqtt") + mock_config_entry.add_to_hass(hass) + with patch("homeassistant.components.mqtt.async_subscribe") as mock_subscribe: + await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + mock_subscribe.assert_not_called() + assert hass.states.get("switch.amazon_fire_screensaver") + + def has_subscribed(mqtt_mock: MqttMockHAClient, topic: str) -> bool: """Check if MQTT topic has subscription.""" for call in mqtt_mock.async_subscribe.call_args_list: