"""Tests for Comelit SimpleHome utils.""" from unittest.mock import AsyncMock from aiocomelit.api import ComelitSerialBridgeObject from aiocomelit.const import CLIMATE, WATT from aiocomelit.exceptions import ( CannotAuthenticate, CannotConnect, CannotRetrieveData, DeviceStorageFailureError, ) import pytest from homeassistant.components.climate import HVACMode from homeassistant.components.comelit.const import DOMAIN from homeassistant.components.humidifier import ATTR_HUMIDITY from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN, SERVICE_TURN_ON from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState from homeassistant.const import ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_OFF, STATE_ON from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from . import setup_integration from tests.common import MockConfigEntry ENTITY_ID_0 = "switch.switch0" ENTITY_ID_1 = "climate.climate0" ENTITY_ID_2 = "humidifier.climate0_dehumidifier" ENTITY_ID_3 = "humidifier.climate0_humidifier" async def test_device_remove_stale( hass: HomeAssistant, mock_serial_bridge: AsyncMock, mock_serial_bridge_config_entry: MockConfigEntry, ) -> None: """Test removal of stale devices with no entities.""" await setup_integration(hass, mock_serial_bridge_config_entry) assert (state := hass.states.get(ENTITY_ID_1)) assert state.state == HVACMode.HEAT assert state.attributes[ATTR_TEMPERATURE] == 5.0 assert (state := hass.states.get(ENTITY_ID_2)) assert state.state == STATE_OFF assert state.attributes[ATTR_HUMIDITY] == 50.0 assert (state := hass.states.get(ENTITY_ID_3)) assert state.state == STATE_ON assert state.attributes[ATTR_HUMIDITY] == 50.0 mock_serial_bridge.get_all_devices.return_value[CLIMATE] = { 0: ComelitSerialBridgeObject( index=0, name="Climate0", status=0, human_status="off", type="climate", val=[ [0, 0, "O", "A", 0, 0, 0, "N"], [0, 0, "O", "A", 0, 0, 0, "N"], [0, 0], ], protected=0, zone="Living room", power=0.0, power_unit=WATT, ), } await hass.config_entries.async_reload(mock_serial_bridge_config_entry.entry_id) await hass.async_block_till_done() assert (state := hass.states.get(ENTITY_ID_1)) is None assert (state := hass.states.get(ENTITY_ID_2)) is None assert (state := hass.states.get(ENTITY_ID_3)) is None @pytest.mark.parametrize( ("side_effect", "key", "error"), [ (CannotConnect, "cannot_connect", {"error": "CannotConnect()"}), (CannotRetrieveData, "cannot_retrieve_data", {"error": "CannotRetrieveData()"}), (DeviceStorageFailureError, "device_storage_failure", None), ], ) async def test_bridge_api_call_exceptions( hass: HomeAssistant, mock_serial_bridge: AsyncMock, mock_serial_bridge_config_entry: MockConfigEntry, side_effect: type[Exception], key: str, error: dict[str, str] | None, ) -> None: """Test bridge_api_call decorator for exceptions.""" await setup_integration(hass, mock_serial_bridge_config_entry) assert (state := hass.states.get(ENTITY_ID_0)) assert state.state == STATE_OFF mock_serial_bridge.set_device_status.side_effect = side_effect # Call API with pytest.raises(HomeAssistantError) as exc_info: await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: ENTITY_ID_0}, blocking=True, ) assert exc_info.value.translation_domain == DOMAIN assert exc_info.value.translation_key == key assert exc_info.value.translation_placeholders == error async def test_bridge_api_call_reauth( hass: HomeAssistant, mock_serial_bridge: AsyncMock, mock_serial_bridge_config_entry: MockConfigEntry, ) -> None: """Test bridge_api_call decorator for reauth.""" await setup_integration(hass, mock_serial_bridge_config_entry) assert (state := hass.states.get(ENTITY_ID_0)) assert state.state == STATE_OFF mock_serial_bridge.set_device_status.side_effect = CannotAuthenticate # Call API await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: ENTITY_ID_0}, blocking=True, ) assert mock_serial_bridge_config_entry.state is ConfigEntryState.LOADED flows = hass.config_entries.flow.async_progress() assert len(flows) == 1 flow = flows[0] assert flow.get("step_id") == "reauth_confirm" assert flow.get("handler") == DOMAIN assert "context" in flow assert flow["context"].get("source") == SOURCE_REAUTH assert flow["context"].get("entry_id") == mock_serial_bridge_config_entry.entry_id