Add exception translation for switchbot device initialization (#144828)

This commit is contained in:
Retha Runolfsson 2025-05-19 20:22:10 +08:00 committed by GitHub
parent 9d050360c8
commit 0cf503d871
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 120 additions and 3 deletions

View File

@ -24,6 +24,7 @@ from .const import (
CONF_RETRY_COUNT,
CONNECTABLE_SUPPORTED_MODEL_TYPES,
DEFAULT_RETRY_COUNT,
DOMAIN,
ENCRYPTED_MODELS,
HASS_SENSOR_TYPE_TO_SWITCHBOT_MODEL,
SupportedModels,
@ -138,7 +139,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: SwitchbotConfigEntry) ->
)
if not ble_device:
raise ConfigEntryNotReady(
f"Could not find Switchbot {sensor_type} with address {address}"
translation_domain=DOMAIN,
translation_key="device_not_found_error",
translation_placeholders={"sensor_type": sensor_type, "address": address},
)
cls = CLASS_BY_DEVICE.get(sensor_type, switchbot.SwitchbotDevice)
@ -153,7 +156,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: SwitchbotConfigEntry) ->
)
except ValueError as error:
raise ConfigEntryNotReady(
"Invalid encryption configuration provided"
translation_domain=DOMAIN,
translation_key="value_error",
translation_placeholders={"error": str(error)},
) from error
else:
device = cls(
@ -174,7 +179,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: SwitchbotConfigEntry) ->
)
entry.async_on_unload(coordinator.async_start())
if not await coordinator.async_wait_ready():
raise ConfigEntryNotReady(f"{address} is not advertising state")
raise ConfigEntryNotReady(
translation_domain=DOMAIN,
translation_key="advertising_state_error",
translation_placeholders={"address": address},
)
entry.async_on_unload(entry.add_update_listener(_async_update_listener))
await hass.config_entries.async_forward_entry_setups(

View File

@ -197,6 +197,15 @@
"exceptions": {
"operation_error": {
"message": "An error occurred while performing the action: {error}"
},
"value_error": {
"message": "Switchbot device initialization failed because of incorrect configuration parameters: {error}"
},
"advertising_state_error": {
"message": "{address} is not advertising state"
},
"device_not_found_error": {
"message": "Could not find Switchbot {sensor_type} with address {address}"
}
}
}

View File

@ -47,6 +47,14 @@ async def init_integration(hass: HomeAssistant) -> MockConfigEntry:
return entry
def patch_async_ble_device_from_address(return_value: BluetoothServiceInfoBleak | None):
"""Patch async ble device from address to return a given value."""
return patch(
"homeassistant.components.bluetooth.async_ble_device_from_address",
return_value=return_value,
)
WOHAND_SERVICE_INFO = BluetoothServiceInfoBleak(
name="WoHand",
manufacturer_data={89: b"\xfd`0U\x92W"},

View File

@ -0,0 +1,91 @@
"""Test the switchbot init."""
from collections.abc import Callable
from unittest.mock import AsyncMock, patch
import pytest
from homeassistant.core import HomeAssistant
from . import (
HUBMINI_MATTER_SERVICE_INFO,
LOCK_SERVICE_INFO,
patch_async_ble_device_from_address,
)
from tests.common import MockConfigEntry
from tests.components.bluetooth import inject_bluetooth_service_info
@pytest.mark.parametrize(
("exception", "error_message"),
[
(
ValueError("wrong model"),
"Switchbot device initialization failed because of incorrect configuration parameters: wrong model",
),
],
)
async def test_exception_handling_for_device_initialization(
hass: HomeAssistant,
mock_entry_encrypted_factory: Callable[[str], MockConfigEntry],
exception: Exception,
error_message: str,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test exception handling for lock initialization."""
inject_bluetooth_service_info(hass, LOCK_SERVICE_INFO)
entry = mock_entry_encrypted_factory(sensor_type="lock")
entry.add_to_hass(hass)
with patch(
"homeassistant.components.switchbot.lock.switchbot.SwitchbotLock.__init__",
side_effect=exception,
):
await hass.config_entries.async_setup(entry.entry_id)
assert error_message in caplog.text
async def test_setup_entry_without_ble_device(
hass: HomeAssistant,
mock_entry_factory: Callable[[str], MockConfigEntry],
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test setup entry without ble device."""
entry = mock_entry_factory("hygrometer_co2")
entry.add_to_hass(hass)
with patch_async_ble_device_from_address(None):
await hass.config_entries.async_setup(entry.entry_id)
assert (
"Could not find Switchbot hygrometer_co2 with address aa:bb:cc:dd:ee:ff"
in caplog.text
)
async def test_coordinator_wait_ready_timeout(
hass: HomeAssistant,
mock_entry_factory: Callable[[str], MockConfigEntry],
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the coordinator async_wait_ready timeout by calling it directly."""
inject_bluetooth_service_info(hass, HUBMINI_MATTER_SERVICE_INFO)
entry = mock_entry_factory("hubmini_matter")
entry.add_to_hass(hass)
timeout_mock = AsyncMock()
timeout_mock.__aenter__.side_effect = TimeoutError
timeout_mock.__aexit__.return_value = None
with patch(
"homeassistant.components.switchbot.coordinator.asyncio.timeout",
return_value=timeout_mock,
):
await hass.config_entries.async_setup(entry.entry_id)
assert "aa:bb:cc:dd:ee:ff is not advertising state" in caplog.text