From 9e20a13936f30a66da6d8fc305d387300de0a31d Mon Sep 17 00:00:00 2001 From: Brett Adams Date: Tue, 31 Mar 2026 15:53:15 +1000 Subject: [PATCH] Fix Tesla Fleet startup scopes after OAuth refresh (#166922) --- .../components/tesla_fleet/__init__.py | 14 +++++++--- tests/components/tesla_fleet/test_init.py | 26 ++++++++++++++++++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/tesla_fleet/__init__.py b/homeassistant/components/tesla_fleet/__init__.py index f1acf192a32..5ea9ebc040f 100644 --- a/homeassistant/components/tesla_fleet/__init__.py +++ b/homeassistant/components/tesla_fleet/__init__.py @@ -16,7 +16,7 @@ from tesla_fleet_api.exceptions import ( from tesla_fleet_api.tesla import VehicleFleet from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_ACCESS_TOKEN, CONF_TOKEN, Platform +from homeassistant.const import CONF_ACCESS_TOKEN, Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import ( ConfigEntryAuthFailed, @@ -121,7 +121,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: TeslaFleetConfigEntry) - ) raise ConfigEntryAuthFailed from e - access_token = entry.data[CONF_TOKEN][CONF_ACCESS_TOKEN] + oauth_session = OAuth2Session(hass, entry, implementation) + try: + await oauth_session.async_ensure_token_valid() + except OAuth2TokenRequestReauthError as err: + raise ConfigEntryAuthFailed from err + except OAuth2TokenRequestError as err: + raise ConfigEntryNotReady from err + + access_token = oauth_session.token[CONF_ACCESS_TOKEN] session = async_get_clientsession(hass) token = jwt.decode(access_token, options={"verify_signature": False}) @@ -129,8 +137,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: TeslaFleetConfigEntry) - region_code = token["ou_code"].lower() region = region_code if is_valid_region(region_code) else None - oauth_session = OAuth2Session(hass, entry, implementation) - async def _get_access_token() -> str: await oauth_session.async_ensure_token_valid() token: str = oauth_session.token[CONF_ACCESS_TOKEN] diff --git a/tests/components/tesla_fleet/test_init.py b/tests/components/tesla_fleet/test_init.py index 1a2afe76837..47d58e1734f 100644 --- a/tests/components/tesla_fleet/test_init.py +++ b/tests/components/tesla_fleet/test_init.py @@ -19,7 +19,7 @@ from tesla_fleet_api.exceptions import ( VehicleOffline, ) -from homeassistant.components.tesla_fleet.const import DOMAIN +from homeassistant.components.tesla_fleet.const import DOMAIN, SCOPES from homeassistant.components.tesla_fleet.coordinator import ( ENERGY_HISTORY_INTERVAL, ENERGY_INTERVAL, @@ -136,6 +136,30 @@ async def test_oauth_refresh_error( assert normal_config_entry.state is ConfigEntryState.SETUP_RETRY +async def test_setup_uses_scopes_from_refreshed_token( + hass: HomeAssistant, + noscope_config_entry: MockConfigEntry, +) -> None: + """Test setup uses scopes from the refreshed OAuth token.""" + refreshed_token = create_config_entry( + expires_at=3600, + scopes=SCOPES, + ).data[CONF_TOKEN] + + noscope_config_entry.data[CONF_TOKEN]["expires_at"] = 0 + + with patch( + "homeassistant.components.tesla_fleet.oauth.TeslaUserImplementation.async_refresh_token", + return_value=refreshed_token, + ) as mock_async_refresh_token: + await setup_platform(hass, noscope_config_entry) + + mock_async_refresh_token.assert_awaited_once() + assert noscope_config_entry.state is ConfigEntryState.LOADED + assert noscope_config_entry.runtime_data.scopes == SCOPES + assert noscope_config_entry.runtime_data.vehicles + + async def test_invalidate_access_token_updates_when_not_expired( hass: HomeAssistant, normal_config_entry: MockConfigEntry,