diff --git a/tests/components/lock/conftest.py b/tests/components/lock/conftest.py new file mode 100644 index 00000000000..07399a39e92 --- /dev/null +++ b/tests/components/lock/conftest.py @@ -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 diff --git a/tests/components/lock/test_init.py b/tests/components/lock/test_init.py index 637acc22d05..d8589ea265e 100644 --- a/tests/components/lock/test_init.py +++ b/tests/components/lock/test_init.py @@ -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 + )