Add Motionblinds Bluetooth full test coverage (#121878)
* Add tests * Fix entity test * Format * Fix sensor tests * Fix sensor tests * Fix sensor tests * Add init tests * Change service info * Rename test_sensor parameters * Removce ConfigEntryState.LOADED assertion * Remove platforms parameter from setup_platform * Rename setup_platform to setup_integration * Fixture for blind_type and mock_config_entry * Use mock for MotionDevice * Use mock for MotionDevice * Add type hint * Use Mock instead of patch * Use mock_config_entry fixture * Move constants to init * Fix entity_id name * Use fixture * Use fixtures instead of constants * Use display_name fixture * Rename mac to mac_code * Remove one patch * Use fixtures for mock_config_entry * Apply suggestion * Replace patch with mock * Replace patch with mock * Replace patch with mock * Fix * Use pytest.mark.usefixtures if parameter not used * Base mac code on address * Remove if statement from entity test --------- Co-authored-by: Joostlek <joostlek@outlook.com>pull/123613/head^2
parent
f72d9a2c02
commit
c674a25eba
|
@ -1 +1,16 @@
|
||||||
"""Tests for the Motionblinds Bluetooth integration."""
|
"""Tests for the Motionblinds Bluetooth integration."""
|
||||||
|
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_integration(
|
||||||
|
hass: HomeAssistant, mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
|
"""Mock a fully setup config entry."""
|
||||||
|
|
||||||
|
mock_config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
|
@ -3,21 +3,140 @@
|
||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from unittest.mock import AsyncMock, Mock, patch
|
from unittest.mock import AsyncMock, Mock, patch
|
||||||
|
|
||||||
|
from motionblindsble.const import MotionBlindType
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
TEST_MAC = "abcd"
|
from homeassistant.components.bluetooth.models import BluetoothServiceInfoBleak
|
||||||
TEST_NAME = f"MOTION_{TEST_MAC.upper()}"
|
from homeassistant.components.motionblinds_ble.const import (
|
||||||
TEST_ADDRESS = "test_adress"
|
CONF_BLIND_TYPE,
|
||||||
|
CONF_LOCAL_NAME,
|
||||||
|
CONF_MAC_CODE,
|
||||||
|
DOMAIN,
|
||||||
|
)
|
||||||
|
from homeassistant.const import CONF_ADDRESS
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
from tests.components.bluetooth import generate_advertisement_data, generate_ble_device
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="motionblinds_ble_connect", autouse=True)
|
@pytest.fixture
|
||||||
def motion_blinds_connect_fixture(
|
def address() -> str:
|
||||||
enable_bluetooth: None,
|
"""Address fixture."""
|
||||||
|
return "cc:cc:cc:cc:cc:cc"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mac_code(address: str) -> str:
|
||||||
|
"""MAC code fixture."""
|
||||||
|
return "".join(address.split(":")[-3:-1]).upper()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def display_name(mac_code: str) -> str:
|
||||||
|
"""Display name fixture."""
|
||||||
|
return f"Motionblind {mac_code.upper()}"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def name(display_name: str) -> str:
|
||||||
|
"""Name fixture."""
|
||||||
|
return display_name.lower().replace(" ", "_")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def local_name(mac_code: str) -> str:
|
||||||
|
"""Local name fixture."""
|
||||||
|
return f"MOTION_{mac_code.upper()}"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def blind_type() -> MotionBlindType:
|
||||||
|
"""Blind type fixture."""
|
||||||
|
return MotionBlindType.ROLLER
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def service_info(local_name: str, address: str) -> BluetoothServiceInfoBleak:
|
||||||
|
"""Service info fixture."""
|
||||||
|
return BluetoothServiceInfoBleak(
|
||||||
|
name=local_name,
|
||||||
|
address=address,
|
||||||
|
device=generate_ble_device(
|
||||||
|
address=address,
|
||||||
|
name=local_name,
|
||||||
|
),
|
||||||
|
rssi=-61,
|
||||||
|
manufacturer_data={000: b"test"},
|
||||||
|
service_data={
|
||||||
|
"test": bytearray(b"0000"),
|
||||||
|
},
|
||||||
|
service_uuids=[
|
||||||
|
"test",
|
||||||
|
],
|
||||||
|
source="local",
|
||||||
|
advertisement=generate_advertisement_data(
|
||||||
|
manufacturer_data={000: b"test"},
|
||||||
|
service_uuids=["test"],
|
||||||
|
),
|
||||||
|
connectable=True,
|
||||||
|
time=0,
|
||||||
|
tx_power=-127,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_motion_device(
|
||||||
|
blind_type: MotionBlindType, display_name: str
|
||||||
|
) -> Generator[AsyncMock]:
|
||||||
|
"""Mock a MotionDevice."""
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.motionblinds_ble.MotionDevice",
|
||||||
|
autospec=True,
|
||||||
|
) as mock_device:
|
||||||
|
device = mock_device.return_value
|
||||||
|
device.ble_device = Mock()
|
||||||
|
device.display_name = display_name
|
||||||
|
device.blind_type = blind_type
|
||||||
|
yield device
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_config_entry(
|
||||||
|
blind_type: MotionBlindType, address: str, display_name: str, mac_code: str
|
||||||
|
) -> MockConfigEntry:
|
||||||
|
"""Config entry fixture."""
|
||||||
|
return MockConfigEntry(
|
||||||
|
title="mock_title",
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id=address,
|
||||||
|
data={
|
||||||
|
CONF_ADDRESS: address,
|
||||||
|
CONF_LOCAL_NAME: display_name,
|
||||||
|
CONF_MAC_CODE: mac_code,
|
||||||
|
CONF_BLIND_TYPE: blind_type.name.lower(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_setup_entry() -> Generator[AsyncMock]:
|
||||||
|
"""Override async_setup_entry."""
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.motionblinds_ble.async_setup_entry",
|
||||||
|
return_value=True,
|
||||||
|
) as mock_setup_entry:
|
||||||
|
yield mock_setup_entry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def motionblinds_ble_connect(
|
||||||
|
enable_bluetooth: None, local_name: str, address: str
|
||||||
) -> Generator[tuple[AsyncMock, Mock]]:
|
) -> Generator[tuple[AsyncMock, Mock]]:
|
||||||
"""Mock motion blinds ble connection and entry setup."""
|
"""Mock motion blinds ble connection and entry setup."""
|
||||||
device = Mock()
|
device = Mock()
|
||||||
device.name = TEST_NAME
|
device.name = local_name
|
||||||
device.address = TEST_ADDRESS
|
device.address = address
|
||||||
|
|
||||||
bleak_scanner = AsyncMock()
|
bleak_scanner = AsyncMock()
|
||||||
bleak_scanner.discover.return_value = [device]
|
bleak_scanner.discover.return_value = [device]
|
||||||
|
@ -31,9 +150,5 @@ def motion_blinds_connect_fixture(
|
||||||
"homeassistant.components.motionblinds_ble.config_flow.bluetooth.async_get_scanner",
|
"homeassistant.components.motionblinds_ble.config_flow.bluetooth.async_get_scanner",
|
||||||
return_value=bleak_scanner,
|
return_value=bleak_scanner,
|
||||||
),
|
),
|
||||||
patch(
|
|
||||||
"homeassistant.components.motionblinds_ble.async_setup_entry",
|
|
||||||
return_value=True,
|
|
||||||
),
|
|
||||||
):
|
):
|
||||||
yield bleak_scanner, device
|
yield bleak_scanner, device
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
"""Tests for Motionblinds BLE buttons."""
|
||||||
|
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
|
||||||
|
from homeassistant.components.motionblinds_ble.const import (
|
||||||
|
ATTR_CONNECT,
|
||||||
|
ATTR_DISCONNECT,
|
||||||
|
ATTR_FAVORITE,
|
||||||
|
)
|
||||||
|
from homeassistant.const import ATTR_ENTITY_ID
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from . import setup_integration
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("motionblinds_ble_connect")
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("button"),
|
||||||
|
[
|
||||||
|
ATTR_CONNECT,
|
||||||
|
ATTR_DISCONNECT,
|
||||||
|
ATTR_FAVORITE,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_button(
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
mock_motion_device: Mock,
|
||||||
|
name: str,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
button: str,
|
||||||
|
) -> None:
|
||||||
|
"""Test states of the button."""
|
||||||
|
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
BUTTON_DOMAIN,
|
||||||
|
SERVICE_PRESS,
|
||||||
|
{ATTR_ENTITY_ID: f"button.{name}_{button}"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
getattr(mock_motion_device, button).assert_called_once()
|
|
@ -12,41 +12,19 @@ from homeassistant.const import CONF_ADDRESS
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
|
|
||||||
from .conftest import TEST_ADDRESS, TEST_MAC, TEST_NAME
|
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
from tests.components.bluetooth import generate_advertisement_data, generate_ble_device
|
|
||||||
|
|
||||||
TEST_BLIND_TYPE = MotionBlindType.ROLLER.name.lower()
|
|
||||||
|
|
||||||
BLIND_SERVICE_INFO = BluetoothServiceInfoBleak(
|
|
||||||
name=TEST_NAME,
|
|
||||||
address=TEST_ADDRESS,
|
|
||||||
device=generate_ble_device(
|
|
||||||
address="cc:cc:cc:cc:cc:cc",
|
|
||||||
name=TEST_NAME,
|
|
||||||
),
|
|
||||||
rssi=-61,
|
|
||||||
manufacturer_data={000: b"test"},
|
|
||||||
service_data={
|
|
||||||
"test": bytearray(b"0000"),
|
|
||||||
},
|
|
||||||
service_uuids=[
|
|
||||||
"test",
|
|
||||||
],
|
|
||||||
source="local",
|
|
||||||
advertisement=generate_advertisement_data(
|
|
||||||
manufacturer_data={000: b"test"},
|
|
||||||
service_uuids=["test"],
|
|
||||||
),
|
|
||||||
connectable=True,
|
|
||||||
time=0,
|
|
||||||
tx_power=-127,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("motionblinds_ble_connect")
|
@pytest.mark.usefixtures("motionblinds_ble_connect")
|
||||||
async def test_config_flow_manual_success(hass: HomeAssistant) -> None:
|
@pytest.mark.usefixtures("mock_setup_entry")
|
||||||
|
async def test_config_flow_manual_success(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
blind_type: MotionBlindType,
|
||||||
|
mac_code: str,
|
||||||
|
address: str,
|
||||||
|
local_name: str,
|
||||||
|
display_name: str,
|
||||||
|
) -> None:
|
||||||
"""Successful flow manually initialized by the user."""
|
"""Successful flow manually initialized by the user."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
const.DOMAIN, context={"source": config_entries.SOURCE_USER}
|
const.DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
@ -57,28 +35,36 @@ async def test_config_flow_manual_success(hass: HomeAssistant) -> None:
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{const.CONF_MAC_CODE: TEST_MAC},
|
{const.CONF_MAC_CODE: mac_code},
|
||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "confirm"
|
assert result["step_id"] == "confirm"
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{const.CONF_BLIND_TYPE: MotionBlindType.ROLLER.name.lower()},
|
{const.CONF_BLIND_TYPE: blind_type.name.lower()},
|
||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result["title"] == f"Motionblind {TEST_MAC.upper()}"
|
assert result["title"] == display_name
|
||||||
assert result["data"] == {
|
assert result["data"] == {
|
||||||
CONF_ADDRESS: TEST_ADDRESS,
|
CONF_ADDRESS: address,
|
||||||
const.CONF_LOCAL_NAME: TEST_NAME,
|
const.CONF_LOCAL_NAME: local_name,
|
||||||
const.CONF_MAC_CODE: TEST_MAC.upper(),
|
const.CONF_MAC_CODE: mac_code,
|
||||||
const.CONF_BLIND_TYPE: TEST_BLIND_TYPE,
|
const.CONF_BLIND_TYPE: blind_type.name.lower(),
|
||||||
}
|
}
|
||||||
assert result["options"] == {}
|
assert result["options"] == {}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("motionblinds_ble_connect")
|
@pytest.mark.usefixtures("motionblinds_ble_connect")
|
||||||
async def test_config_flow_manual_error_invalid_mac(hass: HomeAssistant) -> None:
|
@pytest.mark.usefixtures("mock_setup_entry")
|
||||||
|
async def test_config_flow_manual_error_invalid_mac(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mac_code: str,
|
||||||
|
address: str,
|
||||||
|
local_name: str,
|
||||||
|
display_name: str,
|
||||||
|
blind_type: MotionBlindType,
|
||||||
|
) -> None:
|
||||||
"""Invalid MAC code error flow manually initialized by the user."""
|
"""Invalid MAC code error flow manually initialized by the user."""
|
||||||
|
|
||||||
# Initialize
|
# Initialize
|
||||||
|
@ -101,7 +87,7 @@ async def test_config_flow_manual_error_invalid_mac(hass: HomeAssistant) -> None
|
||||||
# Recover
|
# Recover
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{const.CONF_MAC_CODE: TEST_MAC},
|
{const.CONF_MAC_CODE: mac_code},
|
||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "confirm"
|
assert result["step_id"] == "confirm"
|
||||||
|
@ -109,15 +95,15 @@ async def test_config_flow_manual_error_invalid_mac(hass: HomeAssistant) -> None
|
||||||
# Finish flow
|
# Finish flow
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{const.CONF_BLIND_TYPE: MotionBlindType.ROLLER.name.lower()},
|
{const.CONF_BLIND_TYPE: blind_type.name.lower()},
|
||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result["title"] == f"Motionblind {TEST_MAC.upper()}"
|
assert result["title"] == display_name
|
||||||
assert result["data"] == {
|
assert result["data"] == {
|
||||||
CONF_ADDRESS: TEST_ADDRESS,
|
CONF_ADDRESS: address,
|
||||||
const.CONF_LOCAL_NAME: TEST_NAME,
|
const.CONF_LOCAL_NAME: local_name,
|
||||||
const.CONF_MAC_CODE: TEST_MAC.upper(),
|
const.CONF_MAC_CODE: mac_code,
|
||||||
const.CONF_BLIND_TYPE: TEST_BLIND_TYPE,
|
const.CONF_BLIND_TYPE: blind_type.name.lower(),
|
||||||
}
|
}
|
||||||
assert result["options"] == {}
|
assert result["options"] == {}
|
||||||
|
|
||||||
|
@ -125,6 +111,7 @@ async def test_config_flow_manual_error_invalid_mac(hass: HomeAssistant) -> None
|
||||||
@pytest.mark.usefixtures("motionblinds_ble_connect")
|
@pytest.mark.usefixtures("motionblinds_ble_connect")
|
||||||
async def test_config_flow_manual_error_no_bluetooth_adapter(
|
async def test_config_flow_manual_error_no_bluetooth_adapter(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
mac_code: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""No Bluetooth adapter error flow manually initialized by the user."""
|
"""No Bluetooth adapter error flow manually initialized by the user."""
|
||||||
|
|
||||||
|
@ -153,14 +140,21 @@ async def test_config_flow_manual_error_no_bluetooth_adapter(
|
||||||
):
|
):
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{const.CONF_MAC_CODE: TEST_MAC},
|
{const.CONF_MAC_CODE: mac_code},
|
||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.ABORT
|
assert result["type"] is FlowResultType.ABORT
|
||||||
assert result["reason"] == const.ERROR_NO_BLUETOOTH_ADAPTER
|
assert result["reason"] == const.ERROR_NO_BLUETOOTH_ADAPTER
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("mock_setup_entry")
|
||||||
async def test_config_flow_manual_error_could_not_find_motor(
|
async def test_config_flow_manual_error_could_not_find_motor(
|
||||||
hass: HomeAssistant, motionblinds_ble_connect: tuple[AsyncMock, Mock]
|
hass: HomeAssistant,
|
||||||
|
motionblinds_ble_connect: tuple[AsyncMock, Mock],
|
||||||
|
mac_code: str,
|
||||||
|
local_name: str,
|
||||||
|
display_name: str,
|
||||||
|
address: str,
|
||||||
|
blind_type: MotionBlindType,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Could not find motor error flow manually initialized by the user."""
|
"""Could not find motor error flow manually initialized by the user."""
|
||||||
|
|
||||||
|
@ -176,17 +170,17 @@ async def test_config_flow_manual_error_could_not_find_motor(
|
||||||
motionblinds_ble_connect[1].name = "WRONG_NAME"
|
motionblinds_ble_connect[1].name = "WRONG_NAME"
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{const.CONF_MAC_CODE: TEST_MAC},
|
{const.CONF_MAC_CODE: mac_code},
|
||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "user"
|
assert result["step_id"] == "user"
|
||||||
assert result["errors"] == {"base": const.ERROR_COULD_NOT_FIND_MOTOR}
|
assert result["errors"] == {"base": const.ERROR_COULD_NOT_FIND_MOTOR}
|
||||||
|
|
||||||
# Recover
|
# Recover
|
||||||
motionblinds_ble_connect[1].name = TEST_NAME
|
motionblinds_ble_connect[1].name = local_name
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{const.CONF_MAC_CODE: TEST_MAC},
|
{const.CONF_MAC_CODE: mac_code},
|
||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "confirm"
|
assert result["step_id"] == "confirm"
|
||||||
|
@ -194,21 +188,23 @@ async def test_config_flow_manual_error_could_not_find_motor(
|
||||||
# Finish flow
|
# Finish flow
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{const.CONF_BLIND_TYPE: MotionBlindType.ROLLER.name.lower()},
|
{const.CONF_BLIND_TYPE: blind_type.name.lower()},
|
||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result["title"] == f"Motionblind {TEST_MAC.upper()}"
|
assert result["title"] == display_name
|
||||||
assert result["data"] == {
|
assert result["data"] == {
|
||||||
CONF_ADDRESS: TEST_ADDRESS,
|
CONF_ADDRESS: address,
|
||||||
const.CONF_LOCAL_NAME: TEST_NAME,
|
const.CONF_LOCAL_NAME: local_name,
|
||||||
const.CONF_MAC_CODE: TEST_MAC.upper(),
|
const.CONF_MAC_CODE: mac_code,
|
||||||
const.CONF_BLIND_TYPE: TEST_BLIND_TYPE,
|
const.CONF_BLIND_TYPE: blind_type.name.lower(),
|
||||||
}
|
}
|
||||||
assert result["options"] == {}
|
assert result["options"] == {}
|
||||||
|
|
||||||
|
|
||||||
async def test_config_flow_manual_error_no_devices_found(
|
async def test_config_flow_manual_error_no_devices_found(
|
||||||
hass: HomeAssistant, motionblinds_ble_connect: tuple[AsyncMock, Mock]
|
hass: HomeAssistant,
|
||||||
|
motionblinds_ble_connect: tuple[AsyncMock, Mock],
|
||||||
|
mac_code: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""No devices found error flow manually initialized by the user."""
|
"""No devices found error flow manually initialized by the user."""
|
||||||
|
|
||||||
|
@ -224,19 +220,27 @@ async def test_config_flow_manual_error_no_devices_found(
|
||||||
motionblinds_ble_connect[0].discover.return_value = []
|
motionblinds_ble_connect[0].discover.return_value = []
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{const.CONF_MAC_CODE: TEST_MAC},
|
{const.CONF_MAC_CODE: mac_code},
|
||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.ABORT
|
assert result["type"] is FlowResultType.ABORT
|
||||||
assert result["reason"] == const.ERROR_NO_DEVICES_FOUND
|
assert result["reason"] == const.ERROR_NO_DEVICES_FOUND
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("motionblinds_ble_connect")
|
@pytest.mark.usefixtures("motionblinds_ble_connect")
|
||||||
async def test_config_flow_bluetooth_success(hass: HomeAssistant) -> None:
|
async def test_config_flow_bluetooth_success(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mac_code: str,
|
||||||
|
service_info: BluetoothServiceInfoBleak,
|
||||||
|
address: str,
|
||||||
|
local_name: str,
|
||||||
|
display_name: str,
|
||||||
|
blind_type: MotionBlindType,
|
||||||
|
) -> None:
|
||||||
"""Successful bluetooth discovery flow."""
|
"""Successful bluetooth discovery flow."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
const.DOMAIN,
|
const.DOMAIN,
|
||||||
context={"source": config_entries.SOURCE_BLUETOOTH},
|
context={"source": config_entries.SOURCE_BLUETOOTH},
|
||||||
data=BLIND_SERVICE_INFO,
|
data=service_info,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
|
@ -244,36 +248,32 @@ async def test_config_flow_bluetooth_success(hass: HomeAssistant) -> None:
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{const.CONF_BLIND_TYPE: MotionBlindType.ROLLER.name.lower()},
|
{const.CONF_BLIND_TYPE: blind_type.name.lower()},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result["title"] == f"Motionblind {TEST_MAC.upper()}"
|
assert result["title"] == display_name
|
||||||
assert result["data"] == {
|
assert result["data"] == {
|
||||||
CONF_ADDRESS: TEST_ADDRESS,
|
CONF_ADDRESS: address,
|
||||||
const.CONF_LOCAL_NAME: TEST_NAME,
|
const.CONF_LOCAL_NAME: local_name,
|
||||||
const.CONF_MAC_CODE: TEST_MAC.upper(),
|
const.CONF_MAC_CODE: mac_code,
|
||||||
const.CONF_BLIND_TYPE: TEST_BLIND_TYPE,
|
const.CONF_BLIND_TYPE: blind_type.name.lower(),
|
||||||
}
|
}
|
||||||
assert result["options"] == {}
|
assert result["options"] == {}
|
||||||
|
|
||||||
|
|
||||||
async def test_options_flow(hass: HomeAssistant) -> None:
|
@pytest.mark.usefixtures("mock_setup_entry")
|
||||||
|
async def test_options_flow(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
"""Test the options flow."""
|
"""Test the options flow."""
|
||||||
entry = MockConfigEntry(
|
mock_config_entry.add_to_hass(hass)
|
||||||
domain=const.DOMAIN,
|
|
||||||
unique_id="0123456789",
|
|
||||||
data={
|
|
||||||
const.CONF_BLIND_TYPE: MotionBlindType.ROLLER,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
entry.add_to_hass(hass)
|
|
||||||
|
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
|
||||||
|
|
||||||
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
result = await hass.config_entries.options.async_init(entry.entry_id)
|
result = await hass.config_entries.options.async_init(mock_config_entry.entry_id)
|
||||||
|
|
||||||
assert result["type"] is FlowResultType.FORM
|
assert result["type"] is FlowResultType.FORM
|
||||||
assert result["step_id"] == "init"
|
assert result["step_id"] == "init"
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
"""Tests for Motionblinds BLE covers."""
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
from motionblindsble.const import MotionBlindType, MotionRunningType
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.cover import (
|
||||||
|
ATTR_POSITION,
|
||||||
|
ATTR_TILT_POSITION,
|
||||||
|
DOMAIN as COVER_DOMAIN,
|
||||||
|
SERVICE_CLOSE_COVER,
|
||||||
|
SERVICE_CLOSE_COVER_TILT,
|
||||||
|
SERVICE_OPEN_COVER,
|
||||||
|
SERVICE_OPEN_COVER_TILT,
|
||||||
|
SERVICE_SET_COVER_POSITION,
|
||||||
|
SERVICE_SET_COVER_TILT_POSITION,
|
||||||
|
SERVICE_STOP_COVER,
|
||||||
|
SERVICE_STOP_COVER_TILT,
|
||||||
|
STATE_CLOSED,
|
||||||
|
STATE_CLOSING,
|
||||||
|
STATE_OPEN,
|
||||||
|
STATE_OPENING,
|
||||||
|
)
|
||||||
|
from homeassistant.const import ATTR_ENTITY_ID
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from . import setup_integration
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("blind_type", [MotionBlindType.VENETIAN])
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("service", "method", "kwargs"),
|
||||||
|
[
|
||||||
|
(SERVICE_OPEN_COVER, "open", {}),
|
||||||
|
(SERVICE_CLOSE_COVER, "close", {}),
|
||||||
|
(SERVICE_OPEN_COVER_TILT, "open_tilt", {}),
|
||||||
|
(SERVICE_CLOSE_COVER_TILT, "close_tilt", {}),
|
||||||
|
(SERVICE_SET_COVER_POSITION, "position", {ATTR_POSITION: 5}),
|
||||||
|
(SERVICE_SET_COVER_TILT_POSITION, "tilt", {ATTR_TILT_POSITION: 10}),
|
||||||
|
(SERVICE_STOP_COVER, "stop", {}),
|
||||||
|
(SERVICE_STOP_COVER_TILT, "stop", {}),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_cover_service(
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
mock_motion_device: Mock,
|
||||||
|
name: str,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
service: str,
|
||||||
|
method: str,
|
||||||
|
kwargs: dict[str, Any],
|
||||||
|
) -> None:
|
||||||
|
"""Test cover service."""
|
||||||
|
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
COVER_DOMAIN,
|
||||||
|
service,
|
||||||
|
{ATTR_ENTITY_ID: f"cover.{name}", **kwargs},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
getattr(mock_motion_device, method).assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("running_type", "state"),
|
||||||
|
[
|
||||||
|
(None, "unknown"),
|
||||||
|
(MotionRunningType.STILL, "unknown"),
|
||||||
|
(MotionRunningType.OPENING, STATE_OPENING),
|
||||||
|
(MotionRunningType.CLOSING, STATE_CLOSING),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_cover_update_running(
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
mock_motion_device: Mock,
|
||||||
|
name: str,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
running_type: str | None,
|
||||||
|
state: str,
|
||||||
|
) -> None:
|
||||||
|
"""Test updating running status."""
|
||||||
|
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
async_update_running = mock_motion_device.register_running_callback.call_args[0][0]
|
||||||
|
|
||||||
|
async_update_running(running_type)
|
||||||
|
assert hass.states.get(f"cover.{name}").state == state
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("position", "tilt", "state"),
|
||||||
|
[
|
||||||
|
(None, None, "unknown"),
|
||||||
|
(0, 0, STATE_OPEN),
|
||||||
|
(50, 90, STATE_OPEN),
|
||||||
|
(100, 180, STATE_CLOSED),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_cover_update_position(
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
mock_motion_device: Mock,
|
||||||
|
name: str,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
position: int,
|
||||||
|
tilt: int,
|
||||||
|
state: str,
|
||||||
|
) -> None:
|
||||||
|
"""Test updating cover position and tilt."""
|
||||||
|
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
async_update_position = mock_motion_device.register_position_callback.call_args[0][
|
||||||
|
0
|
||||||
|
]
|
||||||
|
|
||||||
|
async_update_position(position, tilt)
|
||||||
|
assert hass.states.get(f"cover.{name}").state == state
|
|
@ -0,0 +1,54 @@
|
||||||
|
"""Tests for Motionblinds BLE entities."""
|
||||||
|
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.homeassistant import (
|
||||||
|
DOMAIN as HA_DOMAIN,
|
||||||
|
SERVICE_UPDATE_ENTITY,
|
||||||
|
)
|
||||||
|
from homeassistant.components.motionblinds_ble.const import (
|
||||||
|
ATTR_CONNECT,
|
||||||
|
ATTR_DISCONNECT,
|
||||||
|
ATTR_FAVORITE,
|
||||||
|
ATTR_SPEED,
|
||||||
|
)
|
||||||
|
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
|
from . import setup_integration
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("platform", "entity"),
|
||||||
|
[
|
||||||
|
(Platform.BUTTON, ATTR_CONNECT),
|
||||||
|
(Platform.BUTTON, ATTR_DISCONNECT),
|
||||||
|
(Platform.BUTTON, ATTR_FAVORITE),
|
||||||
|
(Platform.SELECT, ATTR_SPEED),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_entity_update(
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
mock_motion_device: Mock,
|
||||||
|
name: str,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
platform: Platform,
|
||||||
|
entity: str,
|
||||||
|
) -> None:
|
||||||
|
"""Test updating entity using homeassistant.update_entity."""
|
||||||
|
|
||||||
|
await async_setup_component(hass, HA_DOMAIN, {})
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
HA_DOMAIN,
|
||||||
|
SERVICE_UPDATE_ENTITY,
|
||||||
|
{ATTR_ENTITY_ID: f"{platform.name.lower()}.{name}_{entity}"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
getattr(mock_motion_device, "status_query").assert_called_once_with()
|
|
@ -0,0 +1,48 @@
|
||||||
|
"""Tests for Motionblinds BLE init."""
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from homeassistant.components.bluetooth.models import BluetoothServiceInfoBleak
|
||||||
|
from homeassistant.components.motionblinds_ble import options_update_listener
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from . import setup_integration
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
from tests.components.bluetooth import inject_bluetooth_service_info
|
||||||
|
|
||||||
|
|
||||||
|
async def test_options_update_listener(
|
||||||
|
mock_config_entry: MockConfigEntry, hass: HomeAssistant
|
||||||
|
) -> None:
|
||||||
|
"""Test options_update_listener."""
|
||||||
|
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.motionblinds_ble.MotionDevice.set_custom_disconnect_time"
|
||||||
|
) as mock_set_custom_disconnect_time,
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.motionblinds_ble.MotionDevice.set_permanent_connection"
|
||||||
|
) as set_permanent_connection,
|
||||||
|
):
|
||||||
|
await options_update_listener(hass, mock_config_entry)
|
||||||
|
mock_set_custom_disconnect_time.assert_called_once()
|
||||||
|
set_permanent_connection.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_update_ble_device(
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
service_info: BluetoothServiceInfoBleak,
|
||||||
|
) -> None:
|
||||||
|
"""Test async_update_ble_device."""
|
||||||
|
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.motionblinds_ble.MotionDevice.set_ble_device"
|
||||||
|
) as mock_set_ble_device:
|
||||||
|
inject_bluetooth_service_info(hass, service_info)
|
||||||
|
mock_set_ble_device.assert_called_once()
|
|
@ -0,0 +1,76 @@
|
||||||
|
"""Tests for Motionblinds BLE selects."""
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Any
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
from motionblindsble.const import MotionSpeedLevel
|
||||||
|
from motionblindsble.device import MotionDevice
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.motionblinds_ble.const import ATTR_SPEED
|
||||||
|
from homeassistant.components.select import (
|
||||||
|
DOMAIN as SELECT_DOMAIN,
|
||||||
|
SERVICE_SELECT_OPTION,
|
||||||
|
)
|
||||||
|
from homeassistant.const import ATTR_ENTITY_ID, ATTR_OPTION
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from . import setup_integration
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(("select", "args"), [(ATTR_SPEED, MotionSpeedLevel.HIGH)])
|
||||||
|
async def test_select(
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
mock_motion_device: Mock,
|
||||||
|
name: str,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
select: str,
|
||||||
|
args: Any,
|
||||||
|
) -> None:
|
||||||
|
"""Test select."""
|
||||||
|
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
SELECT_DOMAIN,
|
||||||
|
SERVICE_SELECT_OPTION,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: f"select.{name}_{select}",
|
||||||
|
ATTR_OPTION: MotionSpeedLevel.HIGH.value,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
getattr(mock_motion_device, select).assert_called_once_with(args)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("select", "register_callback", "value"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
ATTR_SPEED,
|
||||||
|
lambda device: device.register_speed_callback,
|
||||||
|
MotionSpeedLevel.HIGH,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_select_update(
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
mock_motion_device: Mock,
|
||||||
|
name: str,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
select: str,
|
||||||
|
register_callback: Callable[[MotionDevice], Callable[..., None]],
|
||||||
|
value: type[Enum],
|
||||||
|
) -> None:
|
||||||
|
"""Test select state update."""
|
||||||
|
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
update_func = register_callback(mock_motion_device).call_args[0][0]
|
||||||
|
|
||||||
|
update_func(value)
|
||||||
|
assert hass.states.get(f"select.{name}_{select}").state == str(value.value)
|
|
@ -0,0 +1,107 @@
|
||||||
|
"""Tests for Motionblinds BLE sensors."""
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
|
from typing import Any
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
from motionblindsble.const import (
|
||||||
|
MotionBlindType,
|
||||||
|
MotionCalibrationType,
|
||||||
|
MotionConnectionType,
|
||||||
|
)
|
||||||
|
from motionblindsble.device import MotionDevice
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.motionblinds_ble.const import (
|
||||||
|
ATTR_BATTERY,
|
||||||
|
ATTR_SIGNAL_STRENGTH,
|
||||||
|
)
|
||||||
|
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from . import setup_integration
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("blind_type", [MotionBlindType.CURTAIN])
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("sensor", "register_callback", "initial_value", "args", "expected_value"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"connection_status",
|
||||||
|
lambda device: device.register_connection_callback,
|
||||||
|
MotionConnectionType.DISCONNECTED.value,
|
||||||
|
[MotionConnectionType.CONNECTING],
|
||||||
|
MotionConnectionType.CONNECTING.value,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ATTR_BATTERY,
|
||||||
|
lambda device: device.register_battery_callback,
|
||||||
|
"unknown",
|
||||||
|
[25, True, False],
|
||||||
|
"25",
|
||||||
|
),
|
||||||
|
( # Battery unknown
|
||||||
|
ATTR_BATTERY,
|
||||||
|
lambda device: device.register_battery_callback,
|
||||||
|
"unknown",
|
||||||
|
[None, False, False],
|
||||||
|
"unknown",
|
||||||
|
),
|
||||||
|
( # Wired
|
||||||
|
ATTR_BATTERY,
|
||||||
|
lambda device: device.register_battery_callback,
|
||||||
|
"unknown",
|
||||||
|
[255, False, True],
|
||||||
|
"255",
|
||||||
|
),
|
||||||
|
( # Almost full
|
||||||
|
ATTR_BATTERY,
|
||||||
|
lambda device: device.register_battery_callback,
|
||||||
|
"unknown",
|
||||||
|
[99, False, False],
|
||||||
|
"99",
|
||||||
|
),
|
||||||
|
( # Almost empty
|
||||||
|
ATTR_BATTERY,
|
||||||
|
lambda device: device.register_battery_callback,
|
||||||
|
"unknown",
|
||||||
|
[1, False, False],
|
||||||
|
"1",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"calibration_status",
|
||||||
|
lambda device: device.register_calibration_callback,
|
||||||
|
"unknown",
|
||||||
|
[MotionCalibrationType.CALIBRATING],
|
||||||
|
MotionCalibrationType.CALIBRATING.value,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ATTR_SIGNAL_STRENGTH,
|
||||||
|
lambda device: device.register_signal_strength_callback,
|
||||||
|
"unknown",
|
||||||
|
[-50],
|
||||||
|
"-50",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_sensor(
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
mock_motion_device: Mock,
|
||||||
|
name: str,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
sensor: str,
|
||||||
|
register_callback: Callable[[MotionDevice], Callable[..., None]],
|
||||||
|
initial_value: str,
|
||||||
|
args: list[Any],
|
||||||
|
expected_value: str,
|
||||||
|
) -> None:
|
||||||
|
"""Test sensors."""
|
||||||
|
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
assert hass.states.get(f"{SENSOR_DOMAIN}.{name}_{sensor}").state == initial_value
|
||||||
|
update_func = register_callback(mock_motion_device).call_args[0][0]
|
||||||
|
update_func(*args)
|
||||||
|
assert hass.states.get(f"{SENSOR_DOMAIN}.{name}_{sensor}").state == expected_value
|
Loading…
Reference in New Issue