core/tests/components/ness_alarm/test_init.py

260 lines
8.0 KiB
Python

"""Tests for the ness_alarm component."""
from unittest.mock import MagicMock, patch
from nessclient import ArmingMode, ArmingState
import pytest
from homeassistant.components import alarm_control_panel
from homeassistant.components.alarm_control_panel import AlarmControlPanelState
from homeassistant.components.ness_alarm import (
ATTR_CODE,
ATTR_OUTPUT_ID,
CONF_DEVICE_PORT,
CONF_ZONE_ID,
CONF_ZONE_NAME,
CONF_ZONES,
DOMAIN,
SERVICE_AUX,
SERVICE_PANIC,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
CONF_HOST,
SERVICE_ALARM_ARM_AWAY,
SERVICE_ALARM_ARM_HOME,
SERVICE_ALARM_DISARM,
SERVICE_ALARM_TRIGGER,
STATE_UNKNOWN,
)
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
VALID_CONFIG = {
DOMAIN: {
CONF_HOST: "alarm.local",
CONF_DEVICE_PORT: 1234,
CONF_ZONES: [
{CONF_ZONE_NAME: "Zone 1", CONF_ZONE_ID: 1},
{CONF_ZONE_NAME: "Zone 2", CONF_ZONE_ID: 2},
],
}
}
async def test_setup_platform(hass: HomeAssistant, mock_nessclient) -> None:
"""Test platform setup."""
await async_setup_component(hass, DOMAIN, VALID_CONFIG)
assert hass.services.has_service(DOMAIN, "panic")
assert hass.services.has_service(DOMAIN, "aux")
await hass.async_block_till_done()
assert hass.states.get("alarm_control_panel.alarm_panel") is not None
assert hass.states.get("binary_sensor.zone_1") is not None
assert hass.states.get("binary_sensor.zone_2") is not None
assert mock_nessclient.keepalive.call_count == 1
assert mock_nessclient.update.call_count == 1
async def test_panic_service(hass: HomeAssistant, mock_nessclient) -> None:
"""Test calling panic service."""
await async_setup_component(hass, DOMAIN, VALID_CONFIG)
await hass.services.async_call(
DOMAIN, SERVICE_PANIC, blocking=True, service_data={ATTR_CODE: "1234"}
)
mock_nessclient.panic.assert_awaited_once_with("1234")
async def test_aux_service(hass: HomeAssistant, mock_nessclient) -> None:
"""Test calling aux service."""
await async_setup_component(hass, DOMAIN, VALID_CONFIG)
await hass.services.async_call(
DOMAIN, SERVICE_AUX, blocking=True, service_data={ATTR_OUTPUT_ID: 1}
)
mock_nessclient.aux.assert_awaited_once_with(1, True)
async def test_dispatch_state_change(hass: HomeAssistant, mock_nessclient) -> None:
"""Test calling aux service."""
await async_setup_component(hass, DOMAIN, VALID_CONFIG)
await hass.async_block_till_done()
on_state_change = mock_nessclient.on_state_change.call_args[0][0]
on_state_change(ArmingState.ARMING, None)
await hass.async_block_till_done()
assert hass.states.is_state(
"alarm_control_panel.alarm_panel", AlarmControlPanelState.ARMING
)
async def test_alarm_disarm(hass: HomeAssistant, mock_nessclient) -> None:
"""Test disarm."""
await async_setup_component(hass, DOMAIN, VALID_CONFIG)
await hass.async_block_till_done()
await hass.services.async_call(
alarm_control_panel.DOMAIN,
SERVICE_ALARM_DISARM,
blocking=True,
service_data={
ATTR_ENTITY_ID: "alarm_control_panel.alarm_panel",
ATTR_CODE: "1234",
},
)
mock_nessclient.disarm.assert_called_once_with("1234")
async def test_alarm_arm_away(hass: HomeAssistant, mock_nessclient) -> None:
"""Test disarm."""
await async_setup_component(hass, DOMAIN, VALID_CONFIG)
await hass.async_block_till_done()
await hass.services.async_call(
alarm_control_panel.DOMAIN,
SERVICE_ALARM_ARM_AWAY,
blocking=True,
service_data={
ATTR_ENTITY_ID: "alarm_control_panel.alarm_panel",
ATTR_CODE: "1234",
},
)
mock_nessclient.arm_away.assert_called_once_with("1234")
async def test_alarm_arm_home(hass: HomeAssistant, mock_nessclient) -> None:
"""Test disarm."""
await async_setup_component(hass, DOMAIN, VALID_CONFIG)
await hass.async_block_till_done()
await hass.services.async_call(
alarm_control_panel.DOMAIN,
SERVICE_ALARM_ARM_HOME,
blocking=True,
service_data={
ATTR_ENTITY_ID: "alarm_control_panel.alarm_panel",
ATTR_CODE: "1234",
},
)
mock_nessclient.arm_home.assert_called_once_with("1234")
async def test_alarm_trigger(hass: HomeAssistant, mock_nessclient) -> None:
"""Test disarm."""
await async_setup_component(hass, DOMAIN, VALID_CONFIG)
await hass.async_block_till_done()
await hass.services.async_call(
alarm_control_panel.DOMAIN,
SERVICE_ALARM_TRIGGER,
blocking=True,
service_data={
ATTR_ENTITY_ID: "alarm_control_panel.alarm_panel",
ATTR_CODE: "1234",
},
)
mock_nessclient.panic.assert_called_once_with("1234")
async def test_dispatch_zone_change(hass: HomeAssistant, mock_nessclient) -> None:
"""Test zone change events dispatch a signal to subscribers."""
await async_setup_component(hass, DOMAIN, VALID_CONFIG)
await hass.async_block_till_done()
on_zone_change = mock_nessclient.on_zone_change.call_args[0][0]
on_zone_change(1, True)
await hass.async_block_till_done()
assert hass.states.is_state("binary_sensor.zone_1", "on")
assert hass.states.is_state("binary_sensor.zone_2", "off")
async def test_arming_state_change(hass: HomeAssistant, mock_nessclient) -> None:
"""Test arming state change handing."""
states = [
(ArmingState.UNKNOWN, None, STATE_UNKNOWN),
(ArmingState.DISARMED, None, AlarmControlPanelState.DISARMED),
(ArmingState.ARMING, None, AlarmControlPanelState.ARMING),
(ArmingState.EXIT_DELAY, None, AlarmControlPanelState.ARMING),
(ArmingState.ARMED, None, AlarmControlPanelState.ARMED_AWAY),
(
ArmingState.ARMED,
ArmingMode.ARMED_AWAY,
AlarmControlPanelState.ARMED_AWAY,
),
(
ArmingState.ARMED,
ArmingMode.ARMED_HOME,
AlarmControlPanelState.ARMED_HOME,
),
(
ArmingState.ARMED,
ArmingMode.ARMED_NIGHT,
AlarmControlPanelState.ARMED_NIGHT,
),
(ArmingState.ENTRY_DELAY, None, AlarmControlPanelState.PENDING),
(ArmingState.TRIGGERED, None, AlarmControlPanelState.TRIGGERED),
]
await async_setup_component(hass, DOMAIN, VALID_CONFIG)
await hass.async_block_till_done()
assert hass.states.is_state("alarm_control_panel.alarm_panel", STATE_UNKNOWN)
on_state_change = mock_nessclient.on_state_change.call_args[0][0]
for arming_state, arming_mode, expected_state in states:
on_state_change(arming_state, arming_mode)
await hass.async_block_till_done()
assert hass.states.is_state("alarm_control_panel.alarm_panel", expected_state)
class MockClient:
"""Mock nessclient.Client stub."""
async def panic(self, code):
"""Handle panic."""
async def disarm(self, code):
"""Handle disarm."""
async def arm_away(self, code):
"""Handle arm_away."""
async def arm_home(self, code):
"""Handle arm_home."""
async def aux(self, output_id, state):
"""Handle auxiliary control."""
async def keepalive(self):
"""Handle keepalive."""
async def update(self):
"""Handle update."""
def on_zone_change(self):
"""Handle on_zone_change."""
def on_state_change(self):
"""Handle on_state_change."""
async def close(self):
"""Handle close."""
@pytest.fixture
def mock_nessclient():
"""Mock the nessclient Client constructor.
Replaces nessclient.Client with a Mock which always returns the same
MagicMock() instance.
"""
_mock_instance = MagicMock(MockClient())
_mock_factory = MagicMock()
_mock_factory.return_value = _mock_instance
with patch(
"homeassistant.components.ness_alarm.Client", new=_mock_factory, create=True
):
yield _mock_instance