mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Use mocked entity platform for lock service tests (#105020)
* Use mocked entity platform for lock service tests * Cleanup old mock class * Follow up on code review * Improve mock entity platform * Use entity_id of passed entity instead of constant
This commit is contained in:
parent
5c514b6b19
commit
280637822b
141
tests/components/lock/conftest.py
Normal file
141
tests/components/lock/conftest.py
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
"""Fixtures for the lock entity platform tests."""
|
||||||
|
|
||||||
|
from collections.abc import Generator
|
||||||
|
from typing import Any
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.lock import (
|
||||||
|
DOMAIN as LOCK_DOMAIN,
|
||||||
|
LockEntity,
|
||||||
|
LockEntityFeature,
|
||||||
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry, ConfigFlow
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
from tests.common import (
|
||||||
|
MockConfigEntry,
|
||||||
|
MockModule,
|
||||||
|
MockPlatform,
|
||||||
|
mock_config_flow,
|
||||||
|
mock_integration,
|
||||||
|
mock_platform,
|
||||||
|
)
|
||||||
|
|
||||||
|
TEST_DOMAIN = "test"
|
||||||
|
|
||||||
|
|
||||||
|
class MockLock(LockEntity):
|
||||||
|
"""Mocked lock entity."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
supported_features: LockEntityFeature = LockEntityFeature(0),
|
||||||
|
code_format: str | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the lock."""
|
||||||
|
self.calls_open = MagicMock()
|
||||||
|
self.calls_lock = MagicMock()
|
||||||
|
self.calls_unlock = MagicMock()
|
||||||
|
self._attr_code_format = code_format
|
||||||
|
self._attr_supported_features = supported_features
|
||||||
|
self._attr_has_entity_name = True
|
||||||
|
self._attr_name = "test_lock"
|
||||||
|
self._attr_unique_id = "very_unique_lock_id"
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def lock(self, **kwargs: Any) -> None:
|
||||||
|
"""Mock lock lock calls."""
|
||||||
|
self.calls_lock(**kwargs)
|
||||||
|
|
||||||
|
def unlock(self, **kwargs: Any) -> None:
|
||||||
|
"""Mock lock unlock calls."""
|
||||||
|
self.calls_unlock(**kwargs)
|
||||||
|
|
||||||
|
def open(self, **kwargs: Any) -> None:
|
||||||
|
"""Mock lock open calls."""
|
||||||
|
self.calls_open(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class MockFlow(ConfigFlow):
|
||||||
|
"""Test flow."""
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def config_flow_fixture(hass: HomeAssistant) -> Generator[None, None, None]:
|
||||||
|
"""Mock config flow."""
|
||||||
|
mock_platform(hass, f"{TEST_DOMAIN}.config_flow")
|
||||||
|
|
||||||
|
with mock_config_flow(TEST_DOMAIN, MockFlow):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
async def code_format() -> str | None:
|
||||||
|
"""Return the code format for the test lock entity."""
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="supported_features")
|
||||||
|
async def lock_supported_features() -> LockEntityFeature:
|
||||||
|
"""Return the supported features for the test lock entity."""
|
||||||
|
return LockEntityFeature.OPEN
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="mock_lock_entity")
|
||||||
|
async def setup_lock_platform_test_entity(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
code_format: str | None,
|
||||||
|
supported_features: LockEntityFeature,
|
||||||
|
) -> MagicMock:
|
||||||
|
"""Set up lock entity using an entity platform."""
|
||||||
|
|
||||||
|
async def async_setup_entry_init(
|
||||||
|
hass: HomeAssistant, config_entry: ConfigEntry
|
||||||
|
) -> bool:
|
||||||
|
"""Set up test config entry."""
|
||||||
|
await hass.config_entries.async_forward_entry_setup(config_entry, LOCK_DOMAIN)
|
||||||
|
return True
|
||||||
|
|
||||||
|
MockPlatform(hass, f"{TEST_DOMAIN}.config_flow")
|
||||||
|
mock_integration(
|
||||||
|
hass,
|
||||||
|
MockModule(
|
||||||
|
TEST_DOMAIN,
|
||||||
|
async_setup_entry=async_setup_entry_init,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Unnamed sensor without device class -> no name
|
||||||
|
entity = MockLock(
|
||||||
|
supported_features=supported_features,
|
||||||
|
code_format=code_format,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_setup_entry_platform(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Set up test lock platform via config entry."""
|
||||||
|
async_add_entities([entity])
|
||||||
|
|
||||||
|
mock_platform(
|
||||||
|
hass,
|
||||||
|
f"{TEST_DOMAIN}.{LOCK_DOMAIN}",
|
||||||
|
MockPlatform(async_setup_entry=async_setup_entry_platform),
|
||||||
|
)
|
||||||
|
|
||||||
|
config_entry = MockConfigEntry(domain=TEST_DOMAIN)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get(entity.entity_id)
|
||||||
|
assert state is not None
|
||||||
|
|
||||||
|
return entity
|
@ -2,328 +2,354 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import MagicMock
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.lock import (
|
from homeassistant.components.lock import (
|
||||||
ATTR_CODE,
|
ATTR_CODE,
|
||||||
CONF_DEFAULT_CODE,
|
CONF_DEFAULT_CODE,
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_LOCK,
|
||||||
|
SERVICE_OPEN,
|
||||||
|
SERVICE_UNLOCK,
|
||||||
STATE_JAMMED,
|
STATE_JAMMED,
|
||||||
STATE_LOCKED,
|
STATE_LOCKED,
|
||||||
STATE_LOCKING,
|
STATE_LOCKING,
|
||||||
STATE_UNLOCKED,
|
STATE_UNLOCKED,
|
||||||
STATE_UNLOCKING,
|
STATE_UNLOCKING,
|
||||||
LockEntity,
|
|
||||||
LockEntityFeature,
|
LockEntityFeature,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
import homeassistant.helpers.entity_registry as er
|
import homeassistant.helpers.entity_registry as er
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.helpers.typing import UNDEFINED, UndefinedType
|
||||||
|
|
||||||
from tests.testing_config.custom_components.test.lock import MockLock
|
from .conftest import MockLock
|
||||||
|
|
||||||
|
|
||||||
class MockLockEntity(LockEntity):
|
async def help_test_async_lock_service(
|
||||||
"""Mock lock to use in tests."""
|
hass: HomeAssistant,
|
||||||
|
entity_id: str,
|
||||||
|
service: str,
|
||||||
|
code: str | None | UndefinedType = UNDEFINED,
|
||||||
|
) -> None:
|
||||||
|
"""Help to lock a test lock."""
|
||||||
|
data: dict[str, Any] = {"entity_id": entity_id}
|
||||||
|
if code is not UNDEFINED:
|
||||||
|
data[ATTR_CODE] = code
|
||||||
|
|
||||||
def __init__(
|
await hass.services.async_call(DOMAIN, service, data, blocking=True)
|
||||||
self,
|
|
||||||
code_format: str | None = None,
|
|
||||||
lock_option_default_code: str = "",
|
|
||||||
supported_features: LockEntityFeature = LockEntityFeature(0),
|
|
||||||
) -> None:
|
|
||||||
"""Initialize mock lock entity."""
|
|
||||||
self._attr_supported_features = supported_features
|
|
||||||
self.calls_lock = MagicMock()
|
|
||||||
self.calls_unlock = MagicMock()
|
|
||||||
self.calls_open = MagicMock()
|
|
||||||
if code_format is not None:
|
|
||||||
self._attr_code_format = code_format
|
|
||||||
self._lock_option_default_code = lock_option_default_code
|
|
||||||
|
|
||||||
async def async_lock(self, **kwargs: Any) -> None:
|
|
||||||
"""Lock the lock."""
|
|
||||||
self.calls_lock(kwargs)
|
|
||||||
self._attr_is_locking = False
|
|
||||||
self._attr_is_locked = True
|
|
||||||
|
|
||||||
async def async_unlock(self, **kwargs: Any) -> None:
|
|
||||||
"""Unlock the lock."""
|
|
||||||
self.calls_unlock(kwargs)
|
|
||||||
self._attr_is_unlocking = False
|
|
||||||
self._attr_is_locked = False
|
|
||||||
|
|
||||||
async def async_open(self, **kwargs: Any) -> None:
|
|
||||||
"""Open the door latch."""
|
|
||||||
self.calls_open(kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_lock_default(hass: HomeAssistant) -> None:
|
async def test_lock_default(hass: HomeAssistant, mock_lock_entity: MockLock) -> None:
|
||||||
"""Test lock entity with defaults."""
|
"""Test lock entity with defaults."""
|
||||||
lock = MockLockEntity()
|
|
||||||
lock.hass = hass
|
|
||||||
|
|
||||||
assert lock.code_format is None
|
assert mock_lock_entity.code_format is None
|
||||||
assert lock.state is None
|
assert mock_lock_entity.state is None
|
||||||
|
assert mock_lock_entity.is_jammed is None
|
||||||
|
assert mock_lock_entity.is_locked is None
|
||||||
|
assert mock_lock_entity.is_locking is None
|
||||||
|
assert mock_lock_entity.is_unlocking is None
|
||||||
|
|
||||||
|
|
||||||
async def test_lock_states(hass: HomeAssistant) -> None:
|
async def test_lock_states(hass: HomeAssistant, mock_lock_entity: MockLock) -> None:
|
||||||
"""Test lock entity states."""
|
"""Test lock entity states."""
|
||||||
|
|
||||||
lock = MockLockEntity()
|
assert mock_lock_entity.state is None
|
||||||
lock.hass = hass
|
|
||||||
|
|
||||||
assert lock.state is None
|
mock_lock_entity._attr_is_locking = True
|
||||||
|
assert mock_lock_entity.is_locking
|
||||||
|
assert mock_lock_entity.state == STATE_LOCKING
|
||||||
|
|
||||||
lock._attr_is_locking = True
|
mock_lock_entity._attr_is_locked = True
|
||||||
assert lock.is_locking
|
mock_lock_entity._attr_is_locking = False
|
||||||
assert lock.state == STATE_LOCKING
|
assert mock_lock_entity.is_locked
|
||||||
|
assert mock_lock_entity.state == STATE_LOCKED
|
||||||
|
|
||||||
await lock.async_handle_lock_service()
|
mock_lock_entity._attr_is_unlocking = True
|
||||||
assert lock.is_locked
|
assert mock_lock_entity.is_unlocking
|
||||||
assert lock.state == STATE_LOCKED
|
assert mock_lock_entity.state == STATE_UNLOCKING
|
||||||
|
|
||||||
lock._attr_is_unlocking = True
|
mock_lock_entity._attr_is_locked = False
|
||||||
assert lock.is_unlocking
|
mock_lock_entity._attr_is_unlocking = False
|
||||||
assert lock.state == STATE_UNLOCKING
|
assert not mock_lock_entity.is_locked
|
||||||
|
assert mock_lock_entity.state == STATE_UNLOCKED
|
||||||
|
|
||||||
await lock.async_handle_unlock_service()
|
mock_lock_entity._attr_is_jammed = True
|
||||||
assert not lock.is_locked
|
assert mock_lock_entity.is_jammed
|
||||||
assert lock.state == STATE_UNLOCKED
|
assert mock_lock_entity.state == STATE_JAMMED
|
||||||
|
assert not mock_lock_entity.is_locked
|
||||||
lock._attr_is_jammed = True
|
|
||||||
assert lock.is_jammed
|
|
||||||
assert lock.state == STATE_JAMMED
|
|
||||||
assert not lock.is_locked
|
|
||||||
|
|
||||||
|
|
||||||
async def test_set_default_code_option(
|
@pytest.mark.parametrize(
|
||||||
|
("code_format", "supported_features"),
|
||||||
|
[(r"^\d{4}$", LockEntityFeature.OPEN)],
|
||||||
|
)
|
||||||
|
async def test_set_mock_lock_options(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
enable_custom_integrations: None,
|
mock_lock_entity: MockLock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test default code stored in the registry."""
|
"""Test mock attributes and default code stored in the registry."""
|
||||||
|
|
||||||
entry = entity_registry.async_get_or_create("lock", "test", "very_unique")
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
platform = getattr(hass.components, "test.lock")
|
|
||||||
platform.init(empty=True)
|
|
||||||
platform.ENTITIES["lock1"] = platform.MockLock(
|
|
||||||
name="Test",
|
|
||||||
code_format=r"^\d{4}$",
|
|
||||||
supported_features=LockEntityFeature.OPEN,
|
|
||||||
unique_id="very_unique",
|
|
||||||
)
|
|
||||||
|
|
||||||
assert await async_setup_component(hass, "lock", {"lock": {"platform": "test"}})
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
entity0: MockLock = platform.ENTITIES["lock1"]
|
|
||||||
entity_registry.async_update_entity_options(
|
entity_registry.async_update_entity_options(
|
||||||
entry.entity_id, "lock", {CONF_DEFAULT_CODE: "1234"}
|
"lock.test_lock", "lock", {CONF_DEFAULT_CODE: "1234"}
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert entity0._lock_option_default_code == "1234"
|
assert mock_lock_entity._lock_option_default_code == "1234"
|
||||||
|
state = hass.states.get(mock_lock_entity.entity_id)
|
||||||
|
assert state is not None
|
||||||
|
assert state.attributes["code_format"] == r"^\d{4}$"
|
||||||
|
assert state.attributes["supported_features"] == LockEntityFeature.OPEN
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("code_format", [r"^\d{4}$"])
|
||||||
async def test_default_code_option_update(
|
async def test_default_code_option_update(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
enable_custom_integrations: None,
|
mock_lock_entity: MockLock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test default code stored in the registry is updated."""
|
"""Test default code stored in the registry is updated."""
|
||||||
|
|
||||||
entry = entity_registry.async_get_or_create("lock", "test", "very_unique")
|
assert mock_lock_entity._lock_option_default_code == ""
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
platform = getattr(hass.components, "test.lock")
|
|
||||||
platform.init(empty=True)
|
|
||||||
|
|
||||||
# Pre-register entities
|
|
||||||
entry = entity_registry.async_get_or_create("lock", "test", "very_unique")
|
|
||||||
entity_registry.async_update_entity_options(
|
|
||||||
entry.entity_id,
|
|
||||||
"lock",
|
|
||||||
{
|
|
||||||
"default_code": "5432",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
platform.ENTITIES["lock1"] = platform.MockLock(
|
|
||||||
name="Test",
|
|
||||||
code_format=r"^\d{4}$",
|
|
||||||
supported_features=LockEntityFeature.OPEN,
|
|
||||||
unique_id="very_unique",
|
|
||||||
)
|
|
||||||
|
|
||||||
assert await async_setup_component(hass, "lock", {"lock": {"platform": "test"}})
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
entity0: MockLock = platform.ENTITIES["lock1"]
|
|
||||||
assert entity0._lock_option_default_code == "5432"
|
|
||||||
|
|
||||||
entity_registry.async_update_entity_options(
|
entity_registry.async_update_entity_options(
|
||||||
entry.entity_id, "lock", {CONF_DEFAULT_CODE: "1234"}
|
"lock.test_lock", "lock", {CONF_DEFAULT_CODE: "4321"}
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert entity0._lock_option_default_code == "1234"
|
assert mock_lock_entity._lock_option_default_code == "4321"
|
||||||
|
|
||||||
|
|
||||||
async def test_lock_open_with_code(hass: HomeAssistant) -> None:
|
@pytest.mark.parametrize(
|
||||||
|
("code_format", "supported_features"),
|
||||||
|
[(r"^\d{4}$", LockEntityFeature.OPEN)],
|
||||||
|
)
|
||||||
|
async def test_lock_open_with_code(
|
||||||
|
hass: HomeAssistant, mock_lock_entity: MockLock
|
||||||
|
) -> None:
|
||||||
"""Test lock entity with open service."""
|
"""Test lock entity with open service."""
|
||||||
lock = MockLockEntity(
|
state = hass.states.get(mock_lock_entity.entity_id)
|
||||||
code_format=r"^\d{4}$", supported_features=LockEntityFeature.OPEN
|
assert state.attributes["code_format"] == r"^\d{4}$"
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_OPEN
|
||||||
|
)
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_OPEN, code=""
|
||||||
|
)
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_OPEN, code="HELLO"
|
||||||
|
)
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_OPEN, code="1234"
|
||||||
)
|
)
|
||||||
lock.hass = hass
|
assert mock_lock_entity.calls_open.call_count == 1
|
||||||
|
mock_lock_entity.calls_open.assert_called_with(code="1234")
|
||||||
assert lock.state_attributes == {"code_format": r"^\d{4}$"}
|
|
||||||
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
await lock.async_handle_open_service()
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
await lock.async_handle_open_service(code="")
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
await lock.async_handle_open_service(code="HELLO")
|
|
||||||
await lock.async_handle_open_service(code="1234")
|
|
||||||
assert lock.calls_open.call_count == 1
|
|
||||||
|
|
||||||
|
|
||||||
async def test_lock_lock_with_code(hass: HomeAssistant) -> None:
|
@pytest.mark.parametrize(
|
||||||
|
("code_format", "supported_features"),
|
||||||
|
[(r"^\d{4}$", LockEntityFeature.OPEN)],
|
||||||
|
)
|
||||||
|
async def test_lock_lock_with_code(
|
||||||
|
hass: HomeAssistant, mock_lock_entity: MockLock
|
||||||
|
) -> None:
|
||||||
"""Test lock entity with open service."""
|
"""Test lock entity with open service."""
|
||||||
lock = MockLockEntity(code_format=r"^\d{4}$")
|
state = hass.states.get(mock_lock_entity.entity_id)
|
||||||
lock.hass = hass
|
assert state.attributes["code_format"] == r"^\d{4}$"
|
||||||
|
|
||||||
await lock.async_handle_unlock_service(code="1234")
|
await help_test_async_lock_service(
|
||||||
assert not lock.is_locked
|
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK, code="1234"
|
||||||
|
)
|
||||||
|
mock_lock_entity.calls_unlock.assert_called_with(code="1234")
|
||||||
|
assert mock_lock_entity.calls_lock.call_count == 0
|
||||||
|
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
await lock.async_handle_lock_service()
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_LOCK
|
||||||
|
)
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
await lock.async_handle_lock_service(code="")
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_LOCK, code=""
|
||||||
|
)
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
await lock.async_handle_lock_service(code="HELLO")
|
await help_test_async_lock_service(
|
||||||
await lock.async_handle_lock_service(code="1234")
|
hass, mock_lock_entity.entity_id, SERVICE_LOCK, code="HELLO"
|
||||||
assert lock.is_locked
|
)
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_LOCK, code="1234"
|
||||||
|
)
|
||||||
|
assert mock_lock_entity.calls_lock.call_count == 1
|
||||||
|
mock_lock_entity.calls_lock.assert_called_with(code="1234")
|
||||||
|
|
||||||
|
|
||||||
async def test_lock_unlock_with_code(hass: HomeAssistant) -> None:
|
@pytest.mark.parametrize(
|
||||||
|
("code_format", "supported_features"),
|
||||||
|
[(r"^\d{4}$", LockEntityFeature.OPEN)],
|
||||||
|
)
|
||||||
|
async def test_lock_unlock_with_code(
|
||||||
|
hass: HomeAssistant, mock_lock_entity: MockLock
|
||||||
|
) -> None:
|
||||||
"""Test unlock entity with open service."""
|
"""Test unlock entity with open service."""
|
||||||
lock = MockLockEntity(code_format=r"^\d{4}$")
|
state = hass.states.get(mock_lock_entity.entity_id)
|
||||||
lock.hass = hass
|
assert state.attributes["code_format"] == r"^\d{4}$"
|
||||||
|
|
||||||
await lock.async_handle_lock_service(code="1234")
|
await help_test_async_lock_service(
|
||||||
assert lock.is_locked
|
hass, mock_lock_entity.entity_id, SERVICE_LOCK, code="1234"
|
||||||
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
await lock.async_handle_unlock_service()
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
await lock.async_handle_unlock_service(code="")
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
await lock.async_handle_unlock_service(code="HELLO")
|
|
||||||
await lock.async_handle_unlock_service(code="1234")
|
|
||||||
assert not lock.is_locked
|
|
||||||
|
|
||||||
|
|
||||||
async def test_lock_with_illegal_code(hass: HomeAssistant) -> None:
|
|
||||||
"""Test lock entity with default code that does not match the code format."""
|
|
||||||
lock = MockLockEntity(
|
|
||||||
code_format=r"^\d{4}$",
|
|
||||||
supported_features=LockEntityFeature.OPEN,
|
|
||||||
)
|
)
|
||||||
lock.hass = hass
|
mock_lock_entity.calls_lock.assert_called_with(code="1234")
|
||||||
|
assert mock_lock_entity.calls_unlock.call_count == 0
|
||||||
|
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
await lock.async_handle_open_service(code="123456")
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK
|
||||||
|
)
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
await lock.async_handle_lock_service(code="123456")
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK, code=""
|
||||||
|
)
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
await lock.async_handle_unlock_service(code="123456")
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK, code="HELLO"
|
||||||
|
)
|
||||||
async def test_lock_with_no_code(hass: HomeAssistant) -> None:
|
await help_test_async_lock_service(
|
||||||
"""Test lock entity with default code that does not match the code format."""
|
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK, code="1234"
|
||||||
lock = MockLockEntity(
|
|
||||||
supported_features=LockEntityFeature.OPEN,
|
|
||||||
)
|
)
|
||||||
lock.hass = hass
|
assert mock_lock_entity.calls_unlock.call_count == 1
|
||||||
|
mock_lock_entity.calls_unlock.assert_called_with(code="1234")
|
||||||
await lock.async_handle_open_service()
|
|
||||||
lock.calls_open.assert_called_with({})
|
|
||||||
await lock.async_handle_lock_service()
|
|
||||||
lock.calls_lock.assert_called_with({})
|
|
||||||
await lock.async_handle_unlock_service()
|
|
||||||
lock.calls_unlock.assert_called_with({})
|
|
||||||
|
|
||||||
await lock.async_handle_open_service(code="")
|
|
||||||
lock.calls_open.assert_called_with({})
|
|
||||||
await lock.async_handle_lock_service(code="")
|
|
||||||
lock.calls_lock.assert_called_with({})
|
|
||||||
await lock.async_handle_unlock_service(code="")
|
|
||||||
lock.calls_unlock.assert_called_with({})
|
|
||||||
|
|
||||||
|
|
||||||
async def test_lock_with_default_code(hass: HomeAssistant) -> None:
|
@pytest.mark.parametrize(
|
||||||
|
("code_format", "supported_features"),
|
||||||
|
[(r"^\d{4}$", LockEntityFeature.OPEN)],
|
||||||
|
)
|
||||||
|
async def test_lock_with_illegal_code(
|
||||||
|
hass: HomeAssistant, mock_lock_entity: MockLock
|
||||||
|
) -> None:
|
||||||
|
"""Test lock entity with default code that does not match the code format."""
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_OPEN, code="123456"
|
||||||
|
)
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_LOCK, code="123456"
|
||||||
|
)
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK, code="123456"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("code_format", "supported_features"),
|
||||||
|
[(None, LockEntityFeature.OPEN)],
|
||||||
|
)
|
||||||
|
async def test_lock_with_no_code(
|
||||||
|
hass: HomeAssistant, mock_lock_entity: MockLock
|
||||||
|
) -> None:
|
||||||
|
"""Test lock entity without code."""
|
||||||
|
await help_test_async_lock_service(hass, mock_lock_entity.entity_id, SERVICE_OPEN)
|
||||||
|
mock_lock_entity.calls_open.assert_called_with()
|
||||||
|
await help_test_async_lock_service(hass, mock_lock_entity.entity_id, SERVICE_LOCK)
|
||||||
|
mock_lock_entity.calls_lock.assert_called_with()
|
||||||
|
await help_test_async_lock_service(hass, mock_lock_entity.entity_id, SERVICE_UNLOCK)
|
||||||
|
mock_lock_entity.calls_unlock.assert_called_with()
|
||||||
|
|
||||||
|
mock_lock_entity.calls_open.reset_mock()
|
||||||
|
mock_lock_entity.calls_lock.reset_mock()
|
||||||
|
mock_lock_entity.calls_unlock.reset_mock()
|
||||||
|
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_OPEN, code=""
|
||||||
|
)
|
||||||
|
mock_lock_entity.calls_open.assert_called_with()
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_LOCK, code=""
|
||||||
|
)
|
||||||
|
mock_lock_entity.calls_lock.assert_called_with()
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK, code=""
|
||||||
|
)
|
||||||
|
mock_lock_entity.calls_unlock.assert_called_with()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("code_format", "supported_features"),
|
||||||
|
[(r"^\d{4}$", LockEntityFeature.OPEN)],
|
||||||
|
)
|
||||||
|
async def test_lock_with_default_code(
|
||||||
|
hass: HomeAssistant, entity_registry: er.EntityRegistry, mock_lock_entity: MockLock
|
||||||
|
) -> None:
|
||||||
"""Test lock entity with default code."""
|
"""Test lock entity with default code."""
|
||||||
lock = MockLockEntity(
|
entity_registry.async_update_entity_options(
|
||||||
code_format=r"^\d{4}$",
|
"lock.test_lock", "lock", {CONF_DEFAULT_CODE: "1234"}
|
||||||
supported_features=LockEntityFeature.OPEN,
|
|
||||||
lock_option_default_code="1234",
|
|
||||||
)
|
)
|
||||||
lock.hass = hass
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert lock.state_attributes == {"code_format": r"^\d{4}$"}
|
assert mock_lock_entity.state_attributes == {"code_format": r"^\d{4}$"}
|
||||||
assert lock._lock_option_default_code == "1234"
|
assert mock_lock_entity._lock_option_default_code == "1234"
|
||||||
|
|
||||||
await lock.async_handle_open_service()
|
await help_test_async_lock_service(
|
||||||
lock.calls_open.assert_called_with({ATTR_CODE: "1234"})
|
hass, mock_lock_entity.entity_id, SERVICE_OPEN, code="1234"
|
||||||
await lock.async_handle_lock_service()
|
|
||||||
lock.calls_lock.assert_called_with({ATTR_CODE: "1234"})
|
|
||||||
await lock.async_handle_unlock_service()
|
|
||||||
lock.calls_unlock.assert_called_with({ATTR_CODE: "1234"})
|
|
||||||
|
|
||||||
await lock.async_handle_open_service(code="")
|
|
||||||
lock.calls_open.assert_called_with({ATTR_CODE: "1234"})
|
|
||||||
await lock.async_handle_lock_service(code="")
|
|
||||||
lock.calls_lock.assert_called_with({ATTR_CODE: "1234"})
|
|
||||||
await lock.async_handle_unlock_service(code="")
|
|
||||||
lock.calls_unlock.assert_called_with({ATTR_CODE: "1234"})
|
|
||||||
|
|
||||||
|
|
||||||
async def test_lock_with_provided_and_default_code(hass: HomeAssistant) -> None:
|
|
||||||
"""Test lock entity with provided code when default code is set."""
|
|
||||||
lock = MockLockEntity(
|
|
||||||
code_format=r"^\d{4}$",
|
|
||||||
supported_features=LockEntityFeature.OPEN,
|
|
||||||
lock_option_default_code="1234",
|
|
||||||
)
|
)
|
||||||
lock.hass = hass
|
mock_lock_entity.calls_open.assert_called_with(code="1234")
|
||||||
|
await help_test_async_lock_service(
|
||||||
await lock.async_handle_open_service(code="4321")
|
hass, mock_lock_entity.entity_id, SERVICE_LOCK, code="1234"
|
||||||
lock.calls_open.assert_called_with({ATTR_CODE: "4321"})
|
|
||||||
await lock.async_handle_lock_service(code="4321")
|
|
||||||
lock.calls_lock.assert_called_with({ATTR_CODE: "4321"})
|
|
||||||
await lock.async_handle_unlock_service(code="4321")
|
|
||||||
lock.calls_unlock.assert_called_with({ATTR_CODE: "4321"})
|
|
||||||
|
|
||||||
|
|
||||||
async def test_lock_with_illegal_default_code(hass: HomeAssistant) -> None:
|
|
||||||
"""Test lock entity with default code that does not match the code format."""
|
|
||||||
lock = MockLockEntity(
|
|
||||||
code_format=r"^\d{4}$",
|
|
||||||
supported_features=LockEntityFeature.OPEN,
|
|
||||||
lock_option_default_code="123456",
|
|
||||||
)
|
)
|
||||||
lock.hass = hass
|
mock_lock_entity.calls_lock.assert_called_with(code="1234")
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK, code="1234"
|
||||||
|
)
|
||||||
|
mock_lock_entity.calls_unlock.assert_called_with(code="1234")
|
||||||
|
|
||||||
assert lock.state_attributes == {"code_format": r"^\d{4}$"}
|
mock_lock_entity.calls_open.reset_mock()
|
||||||
assert lock._lock_option_default_code == "123456"
|
mock_lock_entity.calls_lock.reset_mock()
|
||||||
|
mock_lock_entity.calls_unlock.reset_mock()
|
||||||
|
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_OPEN, code=""
|
||||||
|
)
|
||||||
|
mock_lock_entity.calls_open.assert_called_with(code="1234")
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_LOCK, code=""
|
||||||
|
)
|
||||||
|
mock_lock_entity.calls_lock.assert_called_with(code="1234")
|
||||||
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK, code=""
|
||||||
|
)
|
||||||
|
mock_lock_entity.calls_unlock.assert_called_with(code="1234")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("code_format", "supported_features"),
|
||||||
|
[(r"^\d{4}$", LockEntityFeature.OPEN)],
|
||||||
|
)
|
||||||
|
async def test_lock_with_illegal_default_code(
|
||||||
|
hass: HomeAssistant, entity_registry: er.EntityRegistry, mock_lock_entity: MockLock
|
||||||
|
) -> None:
|
||||||
|
"""Test lock entity with illegal default code."""
|
||||||
|
entity_registry.async_update_entity_options(
|
||||||
|
"lock.test_lock", "lock", {CONF_DEFAULT_CODE: "123456"}
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert mock_lock_entity.state_attributes == {"code_format": r"^\d{4}$"}
|
||||||
|
assert mock_lock_entity._lock_option_default_code == ""
|
||||||
|
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
await lock.async_handle_open_service()
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_OPEN
|
||||||
|
)
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
await lock.async_handle_lock_service()
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_LOCK
|
||||||
|
)
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
await lock.async_handle_unlock_service()
|
await help_test_async_lock_service(
|
||||||
|
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user