Add tests to MotionMount integration (#137540)

* Add entity tests

* Add __init__ tests

* Cleanup

* Rename mock_motionmount_config_flow to mock_motionmount

* Remove unneeded PropertyMock

* Set defaults on mock_motionmount

* Test proper device is created

* Check whether proper device is created from test_init.py, also without mac

* Find callback and use that to update name
pull/140989/head^2
RJPoelstra 2025-04-07 18:16:44 +02:00 committed by GitHub
parent 79b984d612
commit cd2313d2ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 280 additions and 143 deletions

View File

@ -46,6 +46,7 @@ class MotionMountPresets(MotionMountEntity, SelectEntity):
super().__init__(mm, config_entry)
self._attr_unique_id = f"{self._base_unique_id}-preset"
self._presets: list[motionmount.Preset] = []
self._attr_current_option = None
def _update_options(self, presets: list[motionmount.Preset]) -> None:
"""Convert presets to select options."""

View File

@ -7,6 +7,7 @@ from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo
HOST = "192.168.1.31"
PORT = 23
MAC = bytes.fromhex("c4dd57f8a55f")
TVM_ZEROCONF_SERVICE_TYPE = "_tvm._tcp.local."

View File

@ -6,9 +6,9 @@ from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from homeassistant.components.motionmount.const import DOMAIN
from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.const import CONF_HOST, CONF_PIN, CONF_PORT
from . import HOST, PORT, ZEROCONF_MAC, ZEROCONF_NAME
from . import HOST, MAC, PORT, ZEROCONF_MAC, ZEROCONF_NAME
from tests.common import MockConfigEntry
@ -24,6 +24,17 @@ def mock_config_entry() -> MockConfigEntry:
)
@pytest.fixture
def mock_config_entry_with_pin() -> MockConfigEntry:
"""Return the default mocked config entry."""
return MockConfigEntry(
title=ZEROCONF_NAME,
domain=DOMAIN,
data={CONF_HOST: HOST, CONF_PORT: PORT, CONF_PIN: 1234},
unique_id=ZEROCONF_MAC,
)
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
"""Mock setting up a config entry."""
@ -34,12 +45,14 @@ def mock_setup_entry() -> Generator[AsyncMock]:
@pytest.fixture
def mock_motionmount_config_flow() -> Generator[MagicMock]:
def mock_motionmount() -> Generator[MagicMock]:
"""Return a mocked MotionMount config flow."""
with patch(
"homeassistant.components.motionmount.config_flow.motionmount.MotionMount",
"homeassistant.components.motionmount.motionmount.MotionMount",
autospec=True,
) as motionmount_mock:
client = motionmount_mock.return_value
client.name = ZEROCONF_NAME
client.mac = MAC
yield client

View File

@ -35,10 +35,10 @@ pytestmark = pytest.mark.usefixtures("mock_setup_entry")
async def test_user_connection_error(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the flow is aborted when there is an connection error."""
mock_motionmount_config_flow.connect.side_effect = ConnectionRefusedError()
mock_motionmount.connect.side_effect = ConnectionRefusedError()
user_input = MOCK_USER_INPUT.copy()
@ -54,10 +54,10 @@ async def test_user_connection_error(
async def test_user_connection_error_invalid_hostname(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the flow is aborted when an invalid hostname is provided."""
mock_motionmount_config_flow.connect.side_effect = socket.gaierror()
mock_motionmount.connect.side_effect = socket.gaierror()
user_input = MOCK_USER_INPUT.copy()
@ -73,10 +73,10 @@ async def test_user_connection_error_invalid_hostname(
async def test_user_timeout_error(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the flow is aborted when there is a timeout error."""
mock_motionmount_config_flow.connect.side_effect = TimeoutError()
mock_motionmount.connect.side_effect = TimeoutError()
user_input = MOCK_USER_INPUT.copy()
@ -92,10 +92,10 @@ async def test_user_timeout_error(
async def test_user_not_connected_error(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the flow is aborted when there is a not connected error."""
mock_motionmount_config_flow.connect.side_effect = motionmount.NotConnectedError()
mock_motionmount.connect.side_effect = motionmount.NotConnectedError()
user_input = MOCK_USER_INPUT.copy()
@ -111,13 +111,11 @@ async def test_user_not_connected_error(
async def test_user_response_error_single_device_new_ce_old_pro(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the flow creates an entry when there is a response error."""
type(mock_motionmount_config_flow).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount_config_flow).mac = PropertyMock(
return_value=b"\x00\x00\x00\x00\x00\x00"
)
type(mock_motionmount).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount).mac = PropertyMock(return_value=b"\x00\x00\x00\x00\x00\x00")
user_input = MOCK_USER_INPUT.copy()
@ -139,11 +137,11 @@ async def test_user_response_error_single_device_new_ce_old_pro(
async def test_user_response_error_single_device_new_ce_new_pro(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the flow creates an entry when there is a response error."""
type(mock_motionmount_config_flow).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount_config_flow).mac = PropertyMock(return_value=MAC)
type(mock_motionmount).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount).mac = PropertyMock(return_value=MAC)
user_input = MOCK_USER_INPUT.copy()
@ -167,13 +165,13 @@ async def test_user_response_error_single_device_new_ce_new_pro(
async def test_user_response_error_multi_device_new_ce_new_pro(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the flow is aborted when there are multiple devices."""
mock_config_entry.add_to_hass(hass)
type(mock_motionmount_config_flow).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount_config_flow).mac = PropertyMock(return_value=MAC)
type(mock_motionmount).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount).mac = PropertyMock(return_value=MAC)
user_input = MOCK_USER_INPUT.copy()
@ -190,14 +188,12 @@ async def test_user_response_error_multi_device_new_ce_new_pro(
async def test_user_response_authentication_needed(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that authentication is requested when needed."""
type(mock_motionmount_config_flow).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount_config_flow).mac = PropertyMock(return_value=MAC)
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=False
)
type(mock_motionmount).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount).mac = PropertyMock(return_value=MAC)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=False)
user_input = MOCK_USER_INPUT.copy()
@ -211,12 +207,8 @@ async def test_user_response_authentication_needed(
assert result["step_id"] == "auth"
# Now simulate the user entered the correct pin to finalize the test
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=True
)
type(mock_motionmount_config_flow).can_authenticate = PropertyMock(
return_value=True
)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=True)
type(mock_motionmount).can_authenticate = PropertyMock(return_value=True)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
@ -236,10 +228,10 @@ async def test_user_response_authentication_needed(
async def test_zeroconf_connection_error(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the flow is aborted when there is an connection error."""
mock_motionmount_config_flow.connect.side_effect = ConnectionRefusedError()
mock_motionmount.connect.side_effect = ConnectionRefusedError()
discovery_info = dataclasses.replace(MOCK_ZEROCONF_TVM_SERVICE_INFO_V1)
@ -255,10 +247,10 @@ async def test_zeroconf_connection_error(
async def test_zeroconf_connection_error_invalid_hostname(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the flow is aborted when there is an connection error."""
mock_motionmount_config_flow.connect.side_effect = socket.gaierror()
mock_motionmount.connect.side_effect = socket.gaierror()
discovery_info = dataclasses.replace(MOCK_ZEROCONF_TVM_SERVICE_INFO_V1)
@ -274,10 +266,10 @@ async def test_zeroconf_connection_error_invalid_hostname(
async def test_zeroconf_timout_error(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the flow is aborted when there is a timeout error."""
mock_motionmount_config_flow.connect.side_effect = TimeoutError()
mock_motionmount.connect.side_effect = TimeoutError()
discovery_info = dataclasses.replace(MOCK_ZEROCONF_TVM_SERVICE_INFO_V1)
@ -293,10 +285,10 @@ async def test_zeroconf_timout_error(
async def test_zeroconf_not_connected_error(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the flow is aborted when there is a not connected error."""
mock_motionmount_config_flow.connect.side_effect = motionmount.NotConnectedError()
mock_motionmount.connect.side_effect = motionmount.NotConnectedError()
discovery_info = dataclasses.replace(MOCK_ZEROCONF_TVM_SERVICE_INFO_V1)
@ -312,12 +304,10 @@ async def test_zeroconf_not_connected_error(
async def test_show_zeroconf_form_new_ce_old_pro(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the zeroconf confirmation form is served."""
type(mock_motionmount_config_flow).mac = PropertyMock(
return_value=b"\x00\x00\x00\x00\x00\x00"
)
type(mock_motionmount).mac = PropertyMock(return_value=b"\x00\x00\x00\x00\x00\x00")
discovery_info = dataclasses.replace(MOCK_ZEROCONF_TVM_SERVICE_INFO_V1)
result = await hass.config_entries.flow.async_init(
@ -348,10 +338,10 @@ async def test_show_zeroconf_form_new_ce_old_pro(
async def test_show_zeroconf_form_new_ce_new_pro(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that the zeroconf confirmation form is served."""
type(mock_motionmount_config_flow).mac = PropertyMock(return_value=MAC)
type(mock_motionmount).mac = PropertyMock(return_value=MAC)
discovery_info = dataclasses.replace(MOCK_ZEROCONF_TVM_SERVICE_INFO_V2)
result = await hass.config_entries.flow.async_init(
@ -383,7 +373,7 @@ async def test_show_zeroconf_form_new_ce_new_pro(
async def test_zeroconf_device_exists_abort(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test we abort zeroconf flow if device already configured."""
mock_config_entry.add_to_hass(hass)
@ -402,13 +392,11 @@ async def test_zeroconf_device_exists_abort(
async def test_zeroconf_authentication_needed(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that authentication is requested when needed."""
type(mock_motionmount_config_flow).mac = PropertyMock(return_value=MAC)
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=False
)
type(mock_motionmount).mac = PropertyMock(return_value=MAC)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=False)
discovery_info = dataclasses.replace(MOCK_ZEROCONF_TVM_SERVICE_INFO_V2)
result = await hass.config_entries.flow.async_init(
@ -421,12 +409,8 @@ async def test_zeroconf_authentication_needed(
assert result["step_id"] == "auth"
# Now simulate the user entered the correct pin to finalize the test
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=True
)
type(mock_motionmount_config_flow).can_authenticate = PropertyMock(
return_value=True
)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=True)
type(mock_motionmount).can_authenticate = PropertyMock(return_value=True)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
@ -448,17 +432,13 @@ async def test_zeroconf_authentication_needed(
async def test_authentication_incorrect_then_correct_pin(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that authentication is requested when needed."""
type(mock_motionmount_config_flow).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount_config_flow).mac = PropertyMock(return_value=MAC)
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=False
)
type(mock_motionmount_config_flow).can_authenticate = PropertyMock(
return_value=True
)
type(mock_motionmount).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount).mac = PropertyMock(return_value=MAC)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=False)
type(mock_motionmount).can_authenticate = PropertyMock(return_value=True)
user_input = MOCK_USER_INPUT.copy()
@ -483,9 +463,7 @@ async def test_authentication_incorrect_then_correct_pin(
assert result["errors"][CONF_PIN] == CONF_PIN
# Now simulate the user entered the correct pin to finalize the test
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=True
)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=True)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input=MOCK_PIN_INPUT.copy(),
@ -505,18 +483,14 @@ async def test_authentication_incorrect_then_correct_pin(
async def test_authentication_first_incorrect_pin_to_backoff(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test that authentication is requested when needed."""
type(mock_motionmount_config_flow).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount_config_flow).mac = PropertyMock(return_value=MAC)
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=False
)
type(mock_motionmount_config_flow).can_authenticate = PropertyMock(
side_effect=[True, 1]
)
type(mock_motionmount).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount).mac = PropertyMock(return_value=MAC)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=False)
type(mock_motionmount).can_authenticate = PropertyMock(side_effect=[True, 1])
result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -532,7 +506,7 @@ async def test_authentication_first_incorrect_pin_to_backoff(
user_input=MOCK_PIN_INPUT.copy(),
)
assert mock_motionmount_config_flow.authenticate.called
assert mock_motionmount.authenticate.called
assert result["type"] is FlowResultType.SHOW_PROGRESS
assert result["step_id"] == "backoff"
@ -541,12 +515,8 @@ async def test_authentication_first_incorrect_pin_to_backoff(
await hass.async_block_till_done()
# Now simulate the user entered the correct pin to finalize the test
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=True
)
type(mock_motionmount_config_flow).can_authenticate = PropertyMock(
return_value=True
)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=True)
type(mock_motionmount).can_authenticate = PropertyMock(return_value=True)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
@ -567,16 +537,14 @@ async def test_authentication_first_incorrect_pin_to_backoff(
async def test_authentication_multiple_incorrect_pins(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test that authentication is requested when needed."""
type(mock_motionmount_config_flow).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount_config_flow).mac = PropertyMock(return_value=MAC)
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=False
)
type(mock_motionmount_config_flow).can_authenticate = PropertyMock(return_value=1)
type(mock_motionmount).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount).mac = PropertyMock(return_value=MAC)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=False)
type(mock_motionmount).can_authenticate = PropertyMock(return_value=1)
user_input = MOCK_USER_INPUT.copy()
@ -602,12 +570,8 @@ async def test_authentication_multiple_incorrect_pins(
await hass.async_block_till_done()
# Now simulate the user entered the correct pin to finalize the test
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=True
)
type(mock_motionmount_config_flow).can_authenticate = PropertyMock(
return_value=True
)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=True)
type(mock_motionmount).can_authenticate = PropertyMock(return_value=True)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
@ -628,16 +592,14 @@ async def test_authentication_multiple_incorrect_pins(
async def test_authentication_show_backoff_when_still_running(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test that authentication is requested when needed."""
type(mock_motionmount_config_flow).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount_config_flow).mac = PropertyMock(return_value=MAC)
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=False
)
type(mock_motionmount_config_flow).can_authenticate = PropertyMock(return_value=1)
type(mock_motionmount).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount).mac = PropertyMock(return_value=MAC)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=False)
type(mock_motionmount).can_authenticate = PropertyMock(return_value=1)
result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -671,12 +633,8 @@ async def test_authentication_show_backoff_when_still_running(
await hass.async_block_till_done()
# Now simulate the user entered the correct pin to finalize the test
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=True
)
type(mock_motionmount_config_flow).can_authenticate = PropertyMock(
return_value=True
)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=True)
type(mock_motionmount).can_authenticate = PropertyMock(return_value=True)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
@ -697,17 +655,13 @@ async def test_authentication_show_backoff_when_still_running(
async def test_authentication_correct_pin(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test that authentication is requested when needed."""
type(mock_motionmount_config_flow).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount_config_flow).mac = PropertyMock(return_value=MAC)
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=False
)
type(mock_motionmount_config_flow).can_authenticate = PropertyMock(
return_value=True
)
type(mock_motionmount).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount).mac = PropertyMock(return_value=MAC)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=False)
type(mock_motionmount).can_authenticate = PropertyMock(return_value=True)
user_input = MOCK_USER_INPUT.copy()
@ -720,9 +674,7 @@ async def test_authentication_correct_pin(
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "auth"
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=True
)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=True)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input=MOCK_PIN_INPUT.copy(),
@ -741,11 +693,11 @@ async def test_authentication_correct_pin(
async def test_full_user_flow_implementation(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test the full manual user flow from start to finish."""
type(mock_motionmount_config_flow).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount_config_flow).mac = PropertyMock(return_value=MAC)
type(mock_motionmount).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount).mac = PropertyMock(return_value=MAC)
result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -773,11 +725,11 @@ async def test_full_user_flow_implementation(
async def test_full_zeroconf_flow_implementation(
hass: HomeAssistant,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test the full zeroconf flow from start to finish."""
type(mock_motionmount_config_flow).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount_config_flow).mac = PropertyMock(return_value=MAC)
type(mock_motionmount).name = PropertyMock(return_value=ZEROCONF_NAME)
type(mock_motionmount).mac = PropertyMock(return_value=MAC)
discovery_info = dataclasses.replace(MOCK_ZEROCONF_TVM_SERVICE_INFO_V2)
result = await hass.config_entries.flow.async_init(
@ -808,7 +760,7 @@ async def test_full_zeroconf_flow_implementation(
async def test_full_reauth_flow_implementation(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount_config_flow: MagicMock,
mock_motionmount: MagicMock,
) -> None:
"""Test reauthentication."""
mock_config_entry.add_to_hass(hass)
@ -824,12 +776,8 @@ async def test_full_reauth_flow_implementation(
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "auth"
type(mock_motionmount_config_flow).can_authenticate = PropertyMock(
return_value=True
)
type(mock_motionmount_config_flow).is_authenticated = PropertyMock(
return_value=True
)
type(mock_motionmount).can_authenticate = PropertyMock(return_value=True)
type(mock_motionmount).is_authenticated = PropertyMock(return_value=True)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input=MOCK_PIN_INPUT.copy(),

View File

@ -0,0 +1,47 @@
"""Tests for the MotionMount Entity base."""
from unittest.mock import MagicMock
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.device_registry import format_mac
from . import ZEROCONF_NAME
from tests.common import MockConfigEntry
async def test_entity_rename(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
mock_config_entry: MockConfigEntry,
mock_motionmount: MagicMock,
) -> None:
"""Tests the state attributes."""
mock_config_entry.add_to_hass(hass)
mock_motionmount.is_authenticated = True
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
mac = format_mac(mock_motionmount.mac.hex())
device = device_registry.async_get_device(
connections={(dr.CONNECTION_NETWORK_MAC, mac)}
)
assert device
assert device.name == ZEROCONF_NAME
# Simulate the user changed the name of the device
mock_motionmount.name = "Blub"
for callback in mock_motionmount.add_listener.call_args_list:
callback[0][0]()
await hass.async_block_till_done()
device = device_registry.async_get_device(
connections={(dr.CONNECTION_NETWORK_MAC, mac)}
)
assert device
assert device.name == "Blub"

View File

@ -0,0 +1,129 @@
"""Tests for the MotionMount init."""
from unittest.mock import MagicMock
from homeassistant.components.motionmount import DOMAIN
from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import format_mac
from tests.common import MockConfigEntry
async def test_setup_entry_with_mac(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
mock_config_entry: MockConfigEntry,
mock_motionmount: MagicMock,
) -> None:
"""Tests the state attributes."""
mock_config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
assert mock_config_entry.state is ConfigEntryState.LOADED
mac = format_mac(mock_motionmount.mac.hex())
device = device_registry.async_get_device(
connections={(dr.CONNECTION_NETWORK_MAC, mac)}
)
assert device
assert device.name == mock_config_entry.title
async def test_setup_entry_without_mac(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
mock_config_entry: MockConfigEntry,
mock_motionmount: MagicMock,
) -> None:
"""Tests the state attributes."""
mock_config_entry.add_to_hass(hass)
mock_motionmount.mac = b"\x00\x00\x00\x00\x00\x00"
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
assert mock_config_entry.state is ConfigEntryState.LOADED
device = device_registry.async_get_device(
identifiers={(DOMAIN, mock_config_entry.entry_id)}
)
assert device
assert device.name == mock_config_entry.title
async def test_setup_entry_failed_connect(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount: MagicMock,
) -> None:
"""Tests the state attributes."""
mock_config_entry.add_to_hass(hass)
mock_motionmount.connect.side_effect = TimeoutError()
assert not await hass.config_entries.async_setup(mock_config_entry.entry_id)
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_setup_entry_wrong_device(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount: MagicMock,
) -> None:
"""Tests the state attributes."""
mock_config_entry.add_to_hass(hass)
mock_motionmount.mac = b"\x00\x00\x00\x00\x00\x01"
assert not await hass.config_entries.async_setup(mock_config_entry.entry_id)
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_setup_entry_no_pin(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount: MagicMock,
) -> None:
"""Tests the state attributes."""
mock_config_entry.add_to_hass(hass)
mock_motionmount.is_authenticated = False
assert not await hass.config_entries.async_setup(mock_config_entry.entry_id)
assert mock_config_entry.state is ConfigEntryState.SETUP_ERROR
assert any(mock_config_entry.async_get_active_flows(hass, sources={SOURCE_REAUTH}))
async def test_setup_entry_wrong_pin(
hass: HomeAssistant,
mock_config_entry_with_pin: MockConfigEntry,
mock_motionmount: MagicMock,
) -> None:
"""Tests the state attributes."""
mock_config_entry_with_pin.add_to_hass(hass)
mock_motionmount.is_authenticated = False
assert not await hass.config_entries.async_setup(
mock_config_entry_with_pin.entry_id
)
assert mock_config_entry_with_pin.state is ConfigEntryState.SETUP_ERROR
assert any(
mock_config_entry_with_pin.async_get_active_flows(hass, sources={SOURCE_REAUTH})
)
async def test_unload_entry(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_motionmount: MagicMock,
) -> None:
"""Test entries are unloaded correctly."""
mock_config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
assert await hass.config_entries.async_unload(mock_config_entry.entry_id)
assert mock_motionmount.disconnect.call_count == 1

View File

@ -7,12 +7,10 @@ import pytest
from homeassistant.core import HomeAssistant
from . import ZEROCONF_NAME
from . import MAC, ZEROCONF_NAME
from tests.common import MockConfigEntry
MAC = bytes.fromhex("c4dd57f8a55f")
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
@pytest.mark.parametrize(