diff --git a/homeassistant/components/fitbit/__init__.py b/homeassistant/components/fitbit/__init__.py index f2378797d8d..6b4e1cadbf3 100644 --- a/homeassistant/components/fitbit/__init__.py +++ b/homeassistant/components/fitbit/__init__.py @@ -4,9 +4,12 @@ from homeassistant.const import Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.helpers import config_entry_oauth2_flow +from homeassistant.helpers.config_entry_oauth2_flow import ( + ImplementationUnavailableError, +) from . import api -from .const import FitbitScope +from .const import DOMAIN, FitbitScope from .coordinator import FitbitConfigEntry, FitbitData, FitbitDeviceCoordinator from .exceptions import FitbitApiException, FitbitAuthException from .model import config_from_entry_data @@ -16,11 +19,17 @@ PLATFORMS: list[Platform] = [Platform.SENSOR] async def async_setup_entry(hass: HomeAssistant, entry: FitbitConfigEntry) -> bool: """Set up fitbit from a config entry.""" - implementation = ( - await config_entry_oauth2_flow.async_get_config_entry_implementation( - hass, entry + try: + implementation = ( + await config_entry_oauth2_flow.async_get_config_entry_implementation( + hass, entry + ) ) - ) + except ImplementationUnavailableError as err: + raise ConfigEntryNotReady( + translation_domain=DOMAIN, + translation_key="oauth2_implementation_unavailable", + ) from err session = config_entry_oauth2_flow.OAuth2Session(hass, entry, implementation) fitbit_api = api.OAuthFitbitApi( hass, session, unit_system=entry.data.get("unit_system") diff --git a/homeassistant/components/fitbit/strings.json b/homeassistant/components/fitbit/strings.json index 4d9060b9987..49281a78560 100644 --- a/homeassistant/components/fitbit/strings.json +++ b/homeassistant/components/fitbit/strings.json @@ -121,5 +121,10 @@ "name": "Water" } } + }, + "exceptions": { + "oauth2_implementation_unavailable": { + "message": "[%key:common::exceptions::oauth2_implementation_unavailable::message%]" + } } } diff --git a/tests/components/fitbit/test_init.py b/tests/components/fitbit/test_init.py index 277965848c4..be6b052a840 100644 --- a/tests/components/fitbit/test_init.py +++ b/tests/components/fitbit/test_init.py @@ -2,6 +2,7 @@ from collections.abc import Awaitable, Callable from http import HTTPStatus +from unittest.mock import patch import pytest @@ -12,6 +13,9 @@ from homeassistant.components.fitbit.const import ( ) from homeassistant.config_entries import ConfigEntryState from homeassistant.core import HomeAssistant +from homeassistant.helpers.config_entry_oauth2_flow import ( + ImplementationUnavailableError, +) from .conftest import ( CLIENT_ID, @@ -26,6 +30,23 @@ from tests.common import MockConfigEntry from tests.test_util.aiohttp import AiohttpClientMocker +async def test_oauth_implementation_not_available( + hass: HomeAssistant, + config_entry: MockConfigEntry, +) -> None: + """Test that unavailable OAuth implementation raises ConfigEntryNotReady.""" + config_entry.add_to_hass(hass) + + with patch( + "homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation", + side_effect=ImplementationUnavailableError, + ): + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + assert config_entry.state is ConfigEntryState.SETUP_RETRY + + async def test_setup( hass: HomeAssistant, integration_setup: Callable[[], Awaitable[bool]],