"""Tests for the Risco binary sensors.""" from collections.abc import Callable from typing import Any from unittest.mock import PropertyMock, patch import pytest from homeassistant.components.risco import CannotConnectError, UnauthorizedError from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN from homeassistant.const import SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_OFF, STATE_ON from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from homeassistant.helpers.entity_component import async_update_entity FIRST_ENTITY_ID = "switch.zone_0_bypassed" SECOND_ENTITY_ID = "switch.zone_1_bypassed" @pytest.mark.parametrize("exception", [CannotConnectError, UnauthorizedError]) async def test_error_on_login( hass: HomeAssistant, entity_registry: er.EntityRegistry, login_with_error, cloud_config_entry, ) -> None: """Test error on login.""" await hass.config_entries.async_setup(cloud_config_entry.entry_id) await hass.async_block_till_done() assert not entity_registry.async_is_registered(FIRST_ENTITY_ID) assert not entity_registry.async_is_registered(SECOND_ENTITY_ID) async def test_cloud_setup( hass: HomeAssistant, entity_registry: er.EntityRegistry, two_zone_cloud, setup_risco_cloud, ) -> None: """Test entity setup.""" assert entity_registry.async_is_registered(FIRST_ENTITY_ID) assert entity_registry.async_is_registered(SECOND_ENTITY_ID) async def _check_cloud_state( hass: HomeAssistant, zones: dict[int, Any], bypassed: bool, entity_id: str, zone_id: int, ) -> None: with patch.object( zones[zone_id], "bypassed", new_callable=PropertyMock(return_value=bypassed), ): await async_update_entity(hass, entity_id) await hass.async_block_till_done() expected_bypassed = STATE_ON if bypassed else STATE_OFF assert hass.states.get(entity_id).state == expected_bypassed assert hass.states.get(entity_id).attributes["zone_id"] == zone_id async def test_cloud_states( hass: HomeAssistant, two_zone_cloud, setup_risco_cloud ) -> None: """Test the various alarm states.""" await _check_cloud_state(hass, two_zone_cloud, True, FIRST_ENTITY_ID, 0) await _check_cloud_state(hass, two_zone_cloud, False, FIRST_ENTITY_ID, 0) await _check_cloud_state(hass, two_zone_cloud, True, SECOND_ENTITY_ID, 1) await _check_cloud_state(hass, two_zone_cloud, False, SECOND_ENTITY_ID, 1) async def test_cloud_bypass( hass: HomeAssistant, two_zone_cloud, setup_risco_cloud ) -> None: """Test bypassing a zone.""" with patch("homeassistant.components.risco.RiscoCloud.bypass_zone") as mock: data = {"entity_id": FIRST_ENTITY_ID} await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_ON, service_data=data, blocking=True ) mock.assert_awaited_once_with(0, True) async def test_cloud_unbypass( hass: HomeAssistant, two_zone_cloud, setup_risco_cloud ) -> None: """Test unbypassing a zone.""" with patch("homeassistant.components.risco.RiscoCloud.bypass_zone") as mock: data = {"entity_id": FIRST_ENTITY_ID} await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, service_data=data, blocking=True ) mock.assert_awaited_once_with(0, False) @pytest.mark.parametrize("exception", [CannotConnectError, UnauthorizedError]) async def test_error_on_connect( hass: HomeAssistant, entity_registry: er.EntityRegistry, connect_with_error, local_config_entry, ) -> None: """Test error on connect.""" await hass.config_entries.async_setup(local_config_entry.entry_id) await hass.async_block_till_done() assert not entity_registry.async_is_registered(FIRST_ENTITY_ID) assert not entity_registry.async_is_registered(SECOND_ENTITY_ID) async def test_local_setup( hass: HomeAssistant, entity_registry: er.EntityRegistry, two_zone_local, setup_risco_local, ) -> None: """Test entity setup.""" assert entity_registry.async_is_registered(FIRST_ENTITY_ID) assert entity_registry.async_is_registered(SECOND_ENTITY_ID) async def _check_local_state( hass: HomeAssistant, zones: dict[int, Any], bypassed: bool, entity_id: str, zone_id: int, callback: Callable, ) -> None: with patch.object( zones[zone_id], "bypassed", new_callable=PropertyMock(return_value=bypassed), ): await callback(zone_id, zones[zone_id]) await hass.async_block_till_done() expected_bypassed = STATE_ON if bypassed else STATE_OFF assert hass.states.get(entity_id).state == expected_bypassed assert hass.states.get(entity_id).attributes["zone_id"] == zone_id @pytest.fixture def mock_zone_handler(): """Create a mock for add_zone_handler.""" with patch("homeassistant.components.risco.RiscoLocal.add_zone_handler") as mock: yield mock async def test_local_states( hass: HomeAssistant, two_zone_local, mock_zone_handler, setup_risco_local ) -> None: """Test the various alarm states.""" callback = mock_zone_handler.call_args.args[0] assert callback is not None await _check_local_state(hass, two_zone_local, True, FIRST_ENTITY_ID, 0, callback) await _check_local_state(hass, two_zone_local, False, FIRST_ENTITY_ID, 0, callback) await _check_local_state(hass, two_zone_local, True, SECOND_ENTITY_ID, 1, callback) await _check_local_state(hass, two_zone_local, False, SECOND_ENTITY_ID, 1, callback) async def test_local_bypass( hass: HomeAssistant, two_zone_local, setup_risco_local ) -> None: """Test bypassing a zone.""" with patch.object(two_zone_local[0], "bypass") as mock: data = {"entity_id": FIRST_ENTITY_ID} await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_ON, service_data=data, blocking=True ) mock.assert_awaited_once_with(True) async def test_local_unbypass( hass: HomeAssistant, two_zone_local, setup_risco_local ) -> None: """Test unbypassing a zone.""" with patch.object(two_zone_local[0], "bypass") as mock: data = {"entity_id": FIRST_ENTITY_ID} await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, service_data=data, blocking=True ) mock.assert_awaited_once_with(False)