Add tests for BMW binary_sensor and lock (#118436)
* BMW: Add tests for binary_sensor & lock * Use entity_registry_enabled_by_default fixture * Update tests/components/bmw_connected_drive/test_binary_sensor.py Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Move fixtures to decorator Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Use fixture decorators if possible * Fix rebase * Spelling adjustments Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Use snapshot_platform helper * Spelling * Remove comment --------- Co-authored-by: Richard <rikroe@users.noreply.github.com> Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
This commit is contained in:
parent
67e9e90346
commit
1eb13b48a2
5 changed files with 1902 additions and 5 deletions
|
@ -149,12 +149,7 @@ omit =
|
|||
homeassistant/components/bloomsky/*
|
||||
homeassistant/components/bluesound/*
|
||||
homeassistant/components/bluetooth_tracker/*
|
||||
homeassistant/components/bmw_connected_drive/__init__.py
|
||||
homeassistant/components/bmw_connected_drive/binary_sensor.py
|
||||
homeassistant/components/bmw_connected_drive/coordinator.py
|
||||
homeassistant/components/bmw_connected_drive/lock.py
|
||||
homeassistant/components/bmw_connected_drive/notify.py
|
||||
homeassistant/components/bmw_connected_drive/sensor.py
|
||||
homeassistant/components/bosch_shc/__init__.py
|
||||
homeassistant/components/bosch_shc/binary_sensor.py
|
||||
homeassistant/components/bosch_shc/cover.py
|
||||
|
|
File diff suppressed because it is too large
Load diff
205
tests/components/bmw_connected_drive/snapshots/test_lock.ambr
Normal file
205
tests/components/bmw_connected_drive/snapshots/test_lock.ambr
Normal file
|
@ -0,0 +1,205 @@
|
|||
# serializer version: 1
|
||||
# name: test_entity_state_attrs[lock.i3_rex_lock-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'lock',
|
||||
'entity_category': None,
|
||||
'entity_id': 'lock.i3_rex_lock',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Lock',
|
||||
'platform': 'bmw_connected_drive',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'lock',
|
||||
'unique_id': 'WBY00000000REXI01-lock',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_entity_state_attrs[lock.i3_rex_lock-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by MyBMW',
|
||||
'car': 'i3 (+ REX)',
|
||||
'door_lock_state': 'UNLOCKED',
|
||||
'friendly_name': 'i3 (+ REX) Lock',
|
||||
'supported_features': <LockEntityFeature: 0>,
|
||||
'vin': 'WBY00000000REXI01',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'lock.i3_rex_lock',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unlocked',
|
||||
})
|
||||
# ---
|
||||
# name: test_entity_state_attrs[lock.i4_edrive40_lock-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'lock',
|
||||
'entity_category': None,
|
||||
'entity_id': 'lock.i4_edrive40_lock',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Lock',
|
||||
'platform': 'bmw_connected_drive',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'lock',
|
||||
'unique_id': 'WBA00000000DEMO02-lock',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_entity_state_attrs[lock.i4_edrive40_lock-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by MyBMW',
|
||||
'car': 'i4 eDrive40',
|
||||
'door_lock_state': 'LOCKED',
|
||||
'friendly_name': 'i4 eDrive40 Lock',
|
||||
'supported_features': <LockEntityFeature: 0>,
|
||||
'vin': 'WBA00000000DEMO02',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'lock.i4_edrive40_lock',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'locked',
|
||||
})
|
||||
# ---
|
||||
# name: test_entity_state_attrs[lock.ix_xdrive50_lock-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'lock',
|
||||
'entity_category': None,
|
||||
'entity_id': 'lock.ix_xdrive50_lock',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Lock',
|
||||
'platform': 'bmw_connected_drive',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'lock',
|
||||
'unique_id': 'WBA00000000DEMO01-lock',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_entity_state_attrs[lock.ix_xdrive50_lock-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by MyBMW',
|
||||
'car': 'iX xDrive50',
|
||||
'door_lock_state': 'LOCKED',
|
||||
'friendly_name': 'iX xDrive50 Lock',
|
||||
'supported_features': <LockEntityFeature: 0>,
|
||||
'vin': 'WBA00000000DEMO01',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'lock.ix_xdrive50_lock',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'locked',
|
||||
})
|
||||
# ---
|
||||
# name: test_entity_state_attrs[lock.m340i_xdrive_lock-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'lock',
|
||||
'entity_category': None,
|
||||
'entity_id': 'lock.m340i_xdrive_lock',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Lock',
|
||||
'platform': 'bmw_connected_drive',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'lock',
|
||||
'unique_id': 'WBA00000000DEMO03-lock',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_entity_state_attrs[lock.m340i_xdrive_lock-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by MyBMW',
|
||||
'car': 'M340i xDrive',
|
||||
'door_lock_state': 'LOCKED',
|
||||
'friendly_name': 'M340i xDrive Lock',
|
||||
'supported_features': <LockEntityFeature: 0>,
|
||||
'vin': 'WBA00000000DEMO03',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'lock.m340i_xdrive_lock',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'locked',
|
||||
})
|
||||
# ---
|
35
tests/components/bmw_connected_drive/test_binary_sensor.py
Normal file
35
tests/components/bmw_connected_drive/test_binary_sensor.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
"""Test BMW binary sensors."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from freezegun import freeze_time
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import setup_mocked_integration
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
|
||||
|
||||
@freeze_time("2023-06-22 10:30:00+00:00")
|
||||
@pytest.mark.usefixtures("bmw_fixture")
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_entity_state_attrs(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test binary sensor states and attributes."""
|
||||
|
||||
# Setup component
|
||||
with patch(
|
||||
"homeassistant.components.bmw_connected_drive.PLATFORMS",
|
||||
[Platform.BINARY_SENSOR],
|
||||
):
|
||||
mock_config_entry = await setup_mocked_integration(hass)
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
139
tests/components/bmw_connected_drive/test_lock.py
Normal file
139
tests/components/bmw_connected_drive/test_lock.py
Normal file
|
@ -0,0 +1,139 @@
|
|||
"""Test BMW locks."""
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from bimmer_connected.models import MyBMWRemoteServiceError
|
||||
from bimmer_connected.vehicle.remote_services import RemoteServices
|
||||
from freezegun import freeze_time
|
||||
import pytest
|
||||
import respx
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.recorder.history import get_significant_states
|
||||
from homeassistant.const import STATE_UNKNOWN, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from . import check_remote_service_call, setup_mocked_integration
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
from tests.components.recorder.common import async_wait_recording_done
|
||||
|
||||
|
||||
@freeze_time("2023-06-22 10:30:00+00:00")
|
||||
@pytest.mark.usefixtures("bmw_fixture")
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_entity_state_attrs(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test lock states and attributes."""
|
||||
|
||||
# Setup component
|
||||
with patch(
|
||||
"homeassistant.components.bmw_connected_drive.PLATFORMS", [Platform.LOCK]
|
||||
):
|
||||
mock_config_entry = await setup_mocked_integration(hass)
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("recorder_mock")
|
||||
@pytest.mark.parametrize(
|
||||
("entity_id", "new_value", "old_value", "service", "remote_service"),
|
||||
[
|
||||
(
|
||||
"lock.m340i_xdrive_lock",
|
||||
"locked",
|
||||
"unlocked",
|
||||
"lock",
|
||||
"door-lock",
|
||||
),
|
||||
("lock.m340i_xdrive_lock", "unlocked", "locked", "unlock", "door-unlock"),
|
||||
],
|
||||
)
|
||||
async def test_service_call_success(
|
||||
hass: HomeAssistant,
|
||||
entity_id: str,
|
||||
new_value: str,
|
||||
old_value: str,
|
||||
service: str,
|
||||
remote_service: str,
|
||||
bmw_fixture: respx.Router,
|
||||
) -> None:
|
||||
"""Test successful service call."""
|
||||
|
||||
# Setup component
|
||||
assert await setup_mocked_integration(hass)
|
||||
hass.states.async_set(entity_id, old_value)
|
||||
assert hass.states.get(entity_id).state == old_value
|
||||
|
||||
now = dt_util.utcnow()
|
||||
|
||||
# Test
|
||||
await hass.services.async_call(
|
||||
"lock",
|
||||
service,
|
||||
blocking=True,
|
||||
target={"entity_id": entity_id},
|
||||
)
|
||||
check_remote_service_call(bmw_fixture, remote_service)
|
||||
assert hass.states.get(entity_id).state == new_value
|
||||
|
||||
# wait for the recorder to really store the data
|
||||
await async_wait_recording_done(hass)
|
||||
states = await hass.async_add_executor_job(
|
||||
get_significant_states, hass, now, None, [entity_id]
|
||||
)
|
||||
assert any(s for s in states[entity_id] if s.state == STATE_UNKNOWN) is False
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("bmw_fixture")
|
||||
@pytest.mark.usefixtures("recorder_mock")
|
||||
@pytest.mark.parametrize(
|
||||
("entity_id", "service"),
|
||||
[
|
||||
("lock.m340i_xdrive_lock", "lock"),
|
||||
("lock.m340i_xdrive_lock", "unlock"),
|
||||
],
|
||||
)
|
||||
async def test_service_call_fail(
|
||||
hass: HomeAssistant,
|
||||
entity_id: str,
|
||||
service: str,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""Test failed service call."""
|
||||
|
||||
# Setup component
|
||||
assert await setup_mocked_integration(hass)
|
||||
old_value = hass.states.get(entity_id).state
|
||||
|
||||
now = dt_util.utcnow()
|
||||
|
||||
# Setup exception
|
||||
monkeypatch.setattr(
|
||||
RemoteServices,
|
||||
"trigger_remote_service",
|
||||
AsyncMock(side_effect=MyBMWRemoteServiceError),
|
||||
)
|
||||
|
||||
# Test
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.services.async_call(
|
||||
"lock",
|
||||
service,
|
||||
blocking=True,
|
||||
target={"entity_id": entity_id},
|
||||
)
|
||||
assert hass.states.get(entity_id).state == old_value
|
||||
|
||||
# wait for the recorder to really store the data
|
||||
await async_wait_recording_done(hass)
|
||||
states = await hass.async_add_executor_job(
|
||||
get_significant_states, hass, now, None, [entity_id]
|
||||
)
|
||||
assert states[entity_id][-2].state == STATE_UNKNOWN
|
Loading…
Add table
Reference in a new issue