Ensure state update after BMW remote service execution (#93745)

Co-authored-by: rikroe <rikroe@users.noreply.github.com>
This commit is contained in:
rikroe 2023-05-29 23:28:06 +02:00 committed by GitHub
parent 24290e5d08
commit 52ef4a3b75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 47 additions and 4 deletions

View File

@ -122,7 +122,4 @@ class BMWButton(BMWBaseEntity, ButtonEntity):
)
await self.entity_description.account_function(self.coordinator)
# Always update HA states after a button was executed.
# BMW remote services that change the vehicle's state update the local object
# when executing the service, so only the HA state machine needs further updates.
self.coordinator.async_update_listeners()

View File

@ -68,6 +68,8 @@ class BMWLock(BMWBaseEntity, LockEntity):
self.async_write_ha_state()
await self.vehicle.remote_services.trigger_remote_door_lock()
self.coordinator.async_update_listeners()
async def async_unlock(self, **kwargs: Any) -> None:
"""Unlock the car."""
_LOGGER.debug("%s: unlocking doors", self.vehicle.name)
@ -79,6 +81,8 @@ class BMWLock(BMWBaseEntity, LockEntity):
self.async_write_ha_state()
await self.vehicle.remote_services.trigger_remote_door_unlock()
self.coordinator.async_update_listeners()
@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""

View File

@ -116,3 +116,5 @@ class BMWNumber(BMWBaseEntity, NumberEntity):
await self.entity_description.remote_service(self.vehicle, value)
except MyBMWAPIError as ex:
raise HomeAssistantError(ex) from ex
self.coordinator.async_update_listeners()

View File

@ -124,3 +124,5 @@ class BMWSelect(BMWBaseEntity, SelectEntity):
option,
)
await self.entity_description.remote_service(self.vehicle, option)
self.coordinator.async_update_listeners()

View File

@ -101,9 +101,13 @@ class BMWSwitch(BMWBaseEntity, SwitchEntity):
except MyBMWAPIError as ex:
raise HomeAssistantError(ex) from ex
self.coordinator.async_update_listeners()
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the switch off."""
try:
await self.entity_description.remote_service_off(self.vehicle)
except MyBMWAPIError as ex:
raise HomeAssistantError(ex) from ex
self.coordinator.async_update_listeners()

View File

@ -1,11 +1,15 @@
"""Fixtures for BMW tests."""
from unittest.mock import AsyncMock
from unittest.mock import AsyncMock, Mock
from bimmer_connected.api.authentication import MyBMWAuthentication
from bimmer_connected.vehicle.remote_services import RemoteServices, RemoteServiceStatus
import pytest
from homeassistant.components.bmw_connected_drive.coordinator import (
BMWDataUpdateCoordinator,
)
from . import mock_login, mock_vehicles
@ -20,5 +24,11 @@ async def bmw_fixture(monkeypatch):
AsyncMock(return_value=RemoteServiceStatus({"eventStatus": "EXECUTED"})),
)
monkeypatch.setattr(
BMWDataUpdateCoordinator,
"async_update_listeners",
Mock(),
)
with mock_vehicles():
yield mock_vehicles

View File

@ -7,6 +7,9 @@ import pytest
import respx
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.bmw_connected_drive.coordinator import (
BMWDataUpdateCoordinator,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
@ -43,6 +46,7 @@ async def test_update_triggers_success(
# Setup component
assert await setup_mocked_integration(hass)
BMWDataUpdateCoordinator.async_update_listeners.reset_mock()
# Test
await hass.services.async_call(
@ -53,6 +57,7 @@ async def test_update_triggers_success(
target={"entity_id": entity_id},
)
assert RemoteServices.trigger_remote_service.call_count == 1
assert BMWDataUpdateCoordinator.async_update_listeners.call_count == 1
@pytest.mark.parametrize(
@ -71,6 +76,7 @@ async def test_update_triggers_fail(
# Setup component
assert await setup_mocked_integration(hass)
BMWDataUpdateCoordinator.async_update_listeners.reset_mock()
# Test
with pytest.raises(ValueError):
@ -82,6 +88,7 @@ async def test_update_triggers_fail(
target={"entity_id": entity_id},
)
assert RemoteServices.trigger_remote_service.call_count == 0
assert BMWDataUpdateCoordinator.async_update_listeners.call_count == 0
@pytest.mark.parametrize(
@ -103,6 +110,7 @@ async def test_update_triggers_exceptions(
# Setup component
assert await setup_mocked_integration(hass)
BMWDataUpdateCoordinator.async_update_listeners.reset_mock()
# Setup exception
monkeypatch.setattr(
@ -121,3 +129,4 @@ async def test_update_triggers_exceptions(
target={"entity_id": "number.i4_edrive40_target_soc"},
)
assert RemoteServices.trigger_remote_service.call_count == 1
assert BMWDataUpdateCoordinator.async_update_listeners.call_count == 0

View File

@ -4,6 +4,9 @@ import pytest
import respx
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.bmw_connected_drive.coordinator import (
BMWDataUpdateCoordinator,
)
from homeassistant.core import HomeAssistant
from . import setup_mocked_integration
@ -41,6 +44,7 @@ async def test_update_triggers_success(
# Setup component
assert await setup_mocked_integration(hass)
BMWDataUpdateCoordinator.async_update_listeners.reset_mock()
# Test
await hass.services.async_call(
@ -51,6 +55,7 @@ async def test_update_triggers_success(
target={"entity_id": entity_id},
)
assert RemoteServices.trigger_remote_service.call_count == 1
assert BMWDataUpdateCoordinator.async_update_listeners.call_count == 1
@pytest.mark.parametrize(
@ -69,6 +74,7 @@ async def test_update_triggers_fail(
# Setup component
assert await setup_mocked_integration(hass)
BMWDataUpdateCoordinator.async_update_listeners.reset_mock()
# Test
with pytest.raises(ValueError):
@ -80,3 +86,4 @@ async def test_update_triggers_fail(
target={"entity_id": entity_id},
)
assert RemoteServices.trigger_remote_service.call_count == 0
assert BMWDataUpdateCoordinator.async_update_listeners.call_count == 0

View File

@ -7,6 +7,9 @@ import pytest
import respx
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.bmw_connected_drive.coordinator import (
BMWDataUpdateCoordinator,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
@ -22,6 +25,7 @@ async def test_entity_state_attrs(
# Setup component
assert await setup_mocked_integration(hass)
BMWDataUpdateCoordinator.async_update_listeners.reset_mock()
# Get all switch entities
assert hass.states.async_all("switch") == snapshot
@ -44,6 +48,7 @@ async def test_update_triggers_success(
# Setup component
assert await setup_mocked_integration(hass)
BMWDataUpdateCoordinator.async_update_listeners.reset_mock()
# Test
await hass.services.async_call(
@ -53,6 +58,7 @@ async def test_update_triggers_success(
target={"entity_id": entity_id},
)
assert RemoteServices.trigger_remote_service.call_count == 1
assert BMWDataUpdateCoordinator.async_update_listeners.call_count == 1
@pytest.mark.parametrize(
@ -74,6 +80,7 @@ async def test_update_triggers_exceptions(
# Setup component
assert await setup_mocked_integration(hass)
BMWDataUpdateCoordinator.async_update_listeners.reset_mock()
# Setup exception
monkeypatch.setattr(
@ -98,3 +105,4 @@ async def test_update_triggers_exceptions(
target={"entity_id": "switch.i4_edrive40_climate"},
)
assert RemoteServices.trigger_remote_service.call_count == 2
assert BMWDataUpdateCoordinator.async_update_listeners.call_count == 0