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
2 changed files with 403 additions and 236 deletions
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 typing import Any
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.lock import (
|
||||
ATTR_CODE,
|
||||
CONF_DEFAULT_CODE,
|
||||
DOMAIN,
|
||||
SERVICE_LOCK,
|
||||
SERVICE_OPEN,
|
||||
SERVICE_UNLOCK,
|
||||
STATE_JAMMED,
|
||||
STATE_LOCKED,
|
||||
STATE_LOCKING,
|
||||
STATE_UNLOCKED,
|
||||
STATE_UNLOCKING,
|
||||
LockEntity,
|
||||
LockEntityFeature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
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):
|
||||
"""Mock lock to use in tests."""
|
||||
async def help_test_async_lock_service(
|
||||
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__(
|
||||
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)
|
||||
await hass.services.async_call(DOMAIN, service, data, blocking=True)
|
||||
|
||||
|
||||
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."""
|
||||
lock = MockLockEntity()
|
||||
lock.hass = hass
|
||||
|
||||
assert lock.code_format is None
|
||||
assert lock.state is None
|
||||
assert mock_lock_entity.code_format 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."""
|
||||
|
||||
lock = MockLockEntity()
|
||||
lock.hass = hass
|
||||
assert mock_lock_entity.state is None
|
||||
|
||||
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
|
||||
assert lock.is_locking
|
||||
assert lock.state == STATE_LOCKING
|
||||
mock_lock_entity._attr_is_locked = True
|
||||
mock_lock_entity._attr_is_locking = False
|
||||
assert mock_lock_entity.is_locked
|
||||
assert mock_lock_entity.state == STATE_LOCKED
|
||||
|
||||
await lock.async_handle_lock_service()
|
||||
assert lock.is_locked
|
||||
assert lock.state == STATE_LOCKED
|
||||
mock_lock_entity._attr_is_unlocking = True
|
||||
assert mock_lock_entity.is_unlocking
|
||||
assert mock_lock_entity.state == STATE_UNLOCKING
|
||||
|
||||
lock._attr_is_unlocking = True
|
||||
assert lock.is_unlocking
|
||||
assert lock.state == STATE_UNLOCKING
|
||||
mock_lock_entity._attr_is_locked = False
|
||||
mock_lock_entity._attr_is_unlocking = False
|
||||
assert not mock_lock_entity.is_locked
|
||||
assert mock_lock_entity.state == STATE_UNLOCKED
|
||||
|
||||
await lock.async_handle_unlock_service()
|
||||
assert not lock.is_locked
|
||||
assert lock.state == STATE_UNLOCKED
|
||||
|
||||
lock._attr_is_jammed = True
|
||||
assert lock.is_jammed
|
||||
assert lock.state == STATE_JAMMED
|
||||
assert not lock.is_locked
|
||||
mock_lock_entity._attr_is_jammed = True
|
||||
assert mock_lock_entity.is_jammed
|
||||
assert mock_lock_entity.state == STATE_JAMMED
|
||||
assert not mock_lock_entity.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,
|
||||
entity_registry: er.EntityRegistry,
|
||||
enable_custom_integrations: None,
|
||||
mock_lock_entity: MockLock,
|
||||
) -> None:
|
||||
"""Test 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"]
|
||||
"""Test mock attributes and default code stored in the registry."""
|
||||
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()
|
||||
|
||||
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(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
enable_custom_integrations: None,
|
||||
mock_lock_entity: MockLock,
|
||||
) -> None:
|
||||
"""Test default code stored in the registry is updated."""
|
||||
|
||||
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)
|
||||
|
||||
# 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"
|
||||
assert mock_lock_entity._lock_option_default_code == ""
|
||||
|
||||
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()
|
||||
|
||||
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."""
|
||||
lock = MockLockEntity(
|
||||
code_format=r"^\d{4}$", supported_features=LockEntityFeature.OPEN
|
||||
state = hass.states.get(mock_lock_entity.entity_id)
|
||||
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 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
|
||||
assert mock_lock_entity.calls_open.call_count == 1
|
||||
mock_lock_entity.calls_open.assert_called_with(code="1234")
|
||||
|
||||
|
||||
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."""
|
||||
lock = MockLockEntity(code_format=r"^\d{4}$")
|
||||
lock.hass = hass
|
||||
state = hass.states.get(mock_lock_entity.entity_id)
|
||||
assert state.attributes["code_format"] == r"^\d{4}$"
|
||||
|
||||
await lock.async_handle_unlock_service(code="1234")
|
||||
assert not lock.is_locked
|
||||
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 mock_lock_entity.calls_lock.call_count == 0
|
||||
|
||||
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):
|
||||
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):
|
||||
await lock.async_handle_lock_service(code="HELLO")
|
||||
await lock.async_handle_lock_service(code="1234")
|
||||
assert lock.is_locked
|
||||
await help_test_async_lock_service(
|
||||
hass, mock_lock_entity.entity_id, SERVICE_LOCK, code="HELLO"
|
||||
)
|
||||
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."""
|
||||
lock = MockLockEntity(code_format=r"^\d{4}$")
|
||||
lock.hass = hass
|
||||
state = hass.states.get(mock_lock_entity.entity_id)
|
||||
assert state.attributes["code_format"] == r"^\d{4}$"
|
||||
|
||||
await lock.async_handle_lock_service(code="1234")
|
||||
assert lock.is_locked
|
||||
|
||||
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,
|
||||
await help_test_async_lock_service(
|
||||
hass, mock_lock_entity.entity_id, SERVICE_LOCK, code="1234"
|
||||
)
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
await lock.async_handle_unlock_service(code="123456")
|
||||
|
||||
|
||||
async def test_lock_with_no_code(hass: HomeAssistant) -> None:
|
||||
"""Test lock entity with default code that does not match the code format."""
|
||||
lock = MockLockEntity(
|
||||
supported_features=LockEntityFeature.OPEN,
|
||||
await help_test_async_lock_service(
|
||||
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK, code="HELLO"
|
||||
)
|
||||
await help_test_async_lock_service(
|
||||
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK, code="1234"
|
||||
)
|
||||
lock.hass = hass
|
||||
|
||||
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({})
|
||||
assert mock_lock_entity.calls_unlock.call_count == 1
|
||||
mock_lock_entity.calls_unlock.assert_called_with(code="1234")
|
||||
|
||||
|
||||
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."""
|
||||
lock = MockLockEntity(
|
||||
code_format=r"^\d{4}$",
|
||||
supported_features=LockEntityFeature.OPEN,
|
||||
lock_option_default_code="1234",
|
||||
entity_registry.async_update_entity_options(
|
||||
"lock.test_lock", "lock", {CONF_DEFAULT_CODE: "1234"}
|
||||
)
|
||||
lock.hass = hass
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert lock.state_attributes == {"code_format": r"^\d{4}$"}
|
||||
assert lock._lock_option_default_code == "1234"
|
||||
assert mock_lock_entity.state_attributes == {"code_format": r"^\d{4}$"}
|
||||
assert mock_lock_entity._lock_option_default_code == "1234"
|
||||
|
||||
await lock.async_handle_open_service()
|
||||
lock.calls_open.assert_called_with({ATTR_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",
|
||||
await help_test_async_lock_service(
|
||||
hass, mock_lock_entity.entity_id, SERVICE_OPEN, code="1234"
|
||||
)
|
||||
lock.hass = hass
|
||||
|
||||
await lock.async_handle_open_service(code="4321")
|
||||
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",
|
||||
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="1234"
|
||||
)
|
||||
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}$"}
|
||||
assert lock._lock_option_default_code == "123456"
|
||||
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(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):
|
||||
await lock.async_handle_open_service()
|
||||
await help_test_async_lock_service(
|
||||
hass, mock_lock_entity.entity_id, SERVICE_OPEN
|
||||
)
|
||||
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):
|
||||
await lock.async_handle_unlock_service()
|
||||
await help_test_async_lock_service(
|
||||
hass, mock_lock_entity.entity_id, SERVICE_UNLOCK
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue