Files
core/tests/components/switchbot/test_lock.py
Retha Runolfsson 4271d3f32f Add exception-translations for switchbot integration (#143444)
* add exception handler

* add unit test

* test exception per platform

* optimize unit tests

* update quality scale
2025-05-09 13:09:18 +02:00

157 lines
4.7 KiB
Python

"""Test the switchbot locks."""
from collections.abc import Callable
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from switchbot.devices.device import SwitchbotOperationError
from homeassistant.components.bluetooth import BluetoothServiceInfoBleak
from homeassistant.components.lock import DOMAIN as LOCK_DOMAIN
from homeassistant.const import (
ATTR_ENTITY_ID,
SERVICE_LOCK,
SERVICE_OPEN,
SERVICE_UNLOCK,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from . import LOCK_SERVICE_INFO, WOLOCKPRO_SERVICE_INFO
from tests.common import MockConfigEntry
from tests.components.bluetooth import inject_bluetooth_service_info
@pytest.mark.parametrize(
("sensor_type", "service_info"),
[("lock_pro", WOLOCKPRO_SERVICE_INFO), ("lock", LOCK_SERVICE_INFO)],
)
@pytest.mark.parametrize(
("service", "mock_method"),
[(SERVICE_UNLOCK, "unlock"), (SERVICE_LOCK, "lock")],
)
async def test_lock_services(
hass: HomeAssistant,
mock_entry_encrypted_factory: Callable[[str], MockConfigEntry],
sensor_type: str,
service: str,
mock_method: str,
service_info: BluetoothServiceInfoBleak,
) -> None:
"""Test lock and unlock services on lock and lockpro devices."""
inject_bluetooth_service_info(hass, service_info)
entry = mock_entry_encrypted_factory(sensor_type=sensor_type)
entry.add_to_hass(hass)
with patch(
f"homeassistant.components.switchbot.lock.switchbot.SwitchbotLock.{mock_method}",
) as mocked_instance:
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
entity_id = "lock.test_name"
await hass.services.async_call(
LOCK_DOMAIN,
service,
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
mocked_instance.assert_awaited_once()
@pytest.mark.parametrize(
("sensor_type", "service_info"),
[("lock_pro", WOLOCKPRO_SERVICE_INFO), ("lock", LOCK_SERVICE_INFO)],
)
@pytest.mark.parametrize(
("service", "mock_method"),
[(SERVICE_UNLOCK, "unlock_without_unlatch"), (SERVICE_OPEN, "unlock")],
)
async def test_lock_services_with_night_latch_enabled(
hass: HomeAssistant,
mock_entry_encrypted_factory: Callable[[str], MockConfigEntry],
sensor_type: str,
service: str,
mock_method: str,
service_info: BluetoothServiceInfoBleak,
) -> None:
"""Test lock service when night latch enabled."""
inject_bluetooth_service_info(hass, service_info)
entry = mock_entry_encrypted_factory(sensor_type=sensor_type)
entry.add_to_hass(hass)
mocked_instance = AsyncMock(return_value=True)
with patch.multiple(
"homeassistant.components.switchbot.lock.switchbot.SwitchbotLock",
is_night_latch_enabled=MagicMock(return_value=True),
**{mock_method: mocked_instance},
):
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
entity_id = "lock.test_name"
await hass.services.async_call(
LOCK_DOMAIN,
service,
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)
mocked_instance.assert_awaited_once()
@pytest.mark.parametrize(
("exception", "error_message"),
[
(
SwitchbotOperationError("Operation failed"),
"An error occurred while performing the action: Operation failed",
),
],
)
@pytest.mark.parametrize(
("service", "mock_method"),
[
(SERVICE_LOCK, "lock"),
(SERVICE_OPEN, "unlock"),
(SERVICE_UNLOCK, "unlock_without_unlatch"),
],
)
async def test_exception_handling_lock_service(
hass: HomeAssistant,
mock_entry_encrypted_factory: Callable[[str], MockConfigEntry],
service: str,
mock_method: str,
exception: Exception,
error_message: str,
) -> None:
"""Test exception handling for lock service with exception."""
inject_bluetooth_service_info(hass, LOCK_SERVICE_INFO)
entry = mock_entry_encrypted_factory(sensor_type="lock")
entry.add_to_hass(hass)
entity_id = "lock.test_name"
with patch.multiple(
"homeassistant.components.switchbot.lock.switchbot.SwitchbotLock",
is_night_latch_enabled=MagicMock(return_value=True),
**{mock_method: AsyncMock(side_effect=exception)},
):
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
with pytest.raises(HomeAssistantError, match=error_message):
await hass.services.async_call(
LOCK_DOMAIN,
service,
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)