Allow one retry before raising ConfigEntryAuthFailed for bmw_connected_drive (#99168)

* Allow one retry before raising ConfigEntryAuthFailed

* Move time with freezer

* Update homeassistant/components/bmw_connected_drive/coordinator.py

---------

Co-authored-by: rikroe <rikroe@users.noreply.github.com>
Co-authored-by: G Johansson <goran.johansson@shiftit.se>
This commit is contained in:
Richard Kroegel 2023-08-29 21:41:50 +02:00 committed by GitHub
parent 4508e341c9
commit b403cb41c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 1 deletions

View File

@ -58,7 +58,10 @@ class BMWDataUpdateCoordinator(DataUpdateCoordinator[None]):
try:
await self.account.get_vehicles()
except MyBMWAuthError as err:
# Clear refresh token and trigger reauth
# Allow one retry interval before raising AuthFailed to avoid flaky API issues
if self.last_update_success:
raise UpdateFailed(err) from err
# Clear refresh token and trigger reauth if previous update failed as well
self._update_config_entry_refresh_token(None)
raise ConfigEntryAuthFailed(err) from err
except (MyBMWAPIError, RequestError) as err:

View File

@ -0,0 +1,92 @@
"""Test BMW coordinator."""
from datetime import timedelta
from unittest.mock import patch
from bimmer_connected.models import MyBMWAPIError, MyBMWAuthError
from freezegun.api import FrozenDateTimeFactory
import respx
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.helpers.update_coordinator import UpdateFailed
from . import FIXTURE_CONFIG_ENTRY
from tests.common import MockConfigEntry, async_fire_time_changed
async def test_update_success(hass: HomeAssistant, bmw_fixture: respx.Router) -> None:
"""Test the reauth form."""
config_entry = MockConfigEntry(**FIXTURE_CONFIG_ENTRY)
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert (
hass.data[config_entry.domain][config_entry.entry_id].last_update_success
is True
)
async def test_update_failed(
hass: HomeAssistant, bmw_fixture: respx.Router, freezer: FrozenDateTimeFactory
) -> None:
"""Test the reauth form."""
config_entry = MockConfigEntry(**FIXTURE_CONFIG_ENTRY)
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
coordinator = hass.data[config_entry.domain][config_entry.entry_id]
assert coordinator.last_update_success is True
freezer.tick(timedelta(minutes=5, seconds=1))
async_fire_time_changed(hass)
with patch(
"bimmer_connected.account.MyBMWAccount.get_vehicles",
side_effect=MyBMWAPIError("Test error"),
):
await hass.async_block_till_done()
assert coordinator.last_update_success is False
assert isinstance(coordinator.last_exception, UpdateFailed) is True
async def test_update_reauth(
hass: HomeAssistant, bmw_fixture: respx.Router, freezer: FrozenDateTimeFactory
) -> None:
"""Test the reauth form."""
config_entry = MockConfigEntry(**FIXTURE_CONFIG_ENTRY)
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
coordinator = hass.data[config_entry.domain][config_entry.entry_id]
assert coordinator.last_update_success is True
freezer.tick(timedelta(minutes=5, seconds=1))
async_fire_time_changed(hass)
with patch(
"bimmer_connected.account.MyBMWAccount.get_vehicles",
side_effect=MyBMWAuthError("Test error"),
):
await hass.async_block_till_done()
assert coordinator.last_update_success is False
assert isinstance(coordinator.last_exception, UpdateFailed) is True
freezer.tick(timedelta(minutes=5, seconds=1))
async_fire_time_changed(hass)
with patch(
"bimmer_connected.account.MyBMWAccount.get_vehicles",
side_effect=MyBMWAuthError("Test error"),
):
await hass.async_block_till_done()
assert coordinator.last_update_success is False
assert isinstance(coordinator.last_exception, ConfigEntryAuthFailed) is True