diff --git a/homeassistant/components/tesla_fleet/__init__.py b/homeassistant/components/tesla_fleet/__init__.py index bc837aa4cac..ff50a99748e 100644 --- a/homeassistant/components/tesla_fleet/__init__.py +++ b/homeassistant/components/tesla_fleet/__init__.py @@ -64,6 +64,15 @@ CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) async def async_setup_entry(hass: HomeAssistant, entry: TeslaFleetConfigEntry) -> bool: """Set up TeslaFleet config.""" + try: + implementation = await async_get_config_entry_implementation(hass, entry) + except ValueError as e: + # Remove invalid implementation from config entry then raise AuthFailed + hass.config_entries.async_update_entry( + entry, data={"auth_implementation": None} + ) + raise ConfigEntryAuthFailed from e + access_token = entry.data[CONF_TOKEN][CONF_ACCESS_TOKEN] session = async_get_clientsession(hass) @@ -71,7 +80,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: TeslaFleetConfigEntry) - scopes: list[Scope] = [Scope(s) for s in token["scp"]] region: str = token["ou_code"].lower() - implementation = await async_get_config_entry_implementation(hass, entry) oauth_session = OAuth2Session(hass, entry, implementation) refresh_lock = asyncio.Lock() diff --git a/tests/components/tesla_fleet/conftest.py b/tests/components/tesla_fleet/conftest.py index 0dc5d87984f..2396e2a88f3 100644 --- a/tests/components/tesla_fleet/conftest.py +++ b/tests/components/tesla_fleet/conftest.py @@ -33,7 +33,9 @@ def mock_expires_at() -> int: return time.time() + 3600 -def create_config_entry(expires_at: int, scopes: list[Scope]) -> MockConfigEntry: +def create_config_entry( + expires_at: int, scopes: list[Scope], implementation: str = DOMAIN +) -> MockConfigEntry: """Create Tesla Fleet entry in Home Assistant.""" access_token = jwt.encode( { @@ -51,7 +53,7 @@ def create_config_entry(expires_at: int, scopes: list[Scope]) -> MockConfigEntry title=UID, unique_id=UID, data={ - "auth_implementation": DOMAIN, + "auth_implementation": implementation, "token": { "status": 0, "userid": UID, @@ -90,6 +92,12 @@ def readonly_config_entry(expires_at: int) -> MockConfigEntry: ) +@pytest.fixture +def bad_config_entry(expires_at: int) -> MockConfigEntry: + """Create Tesla Fleet entry in Home Assistant.""" + return create_config_entry(expires_at, SCOPES, "bad") + + @pytest.fixture(autouse=True) def mock_products() -> Generator[AsyncMock]: """Mock Tesla Fleet Api products method.""" diff --git a/tests/components/tesla_fleet/test_init.py b/tests/components/tesla_fleet/test_init.py index 7c17f986663..7e97096e4e8 100644 --- a/tests/components/tesla_fleet/test_init.py +++ b/tests/components/tesla_fleet/test_init.py @@ -30,6 +30,7 @@ from homeassistant.components.tesla_fleet.coordinator import ( from homeassistant.components.tesla_fleet.models import TeslaFleetData from homeassistant.config_entries import ConfigEntryState from homeassistant.core import HomeAssistant +from homeassistant.data_entry_flow import FlowResultType from homeassistant.helpers import device_registry as dr from . import setup_platform @@ -424,3 +425,20 @@ async def test_signing( ) as mock_get_private_key: await setup_platform(hass, normal_config_entry) mock_get_private_key.assert_called_once() + + +async def test_bad_implementation( + hass: HomeAssistant, + bad_config_entry: MockConfigEntry, +) -> None: + """Test handling of a bad authentication implementation.""" + + await setup_platform(hass, bad_config_entry) + assert bad_config_entry.state is ConfigEntryState.SETUP_ERROR + + # Ensure reauth flow starts + assert any(bad_config_entry.async_get_active_flows(hass, {"reauth"})) + result = await bad_config_entry.start_reauth_flow(hass) + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "reauth_confirm" + assert not result["errors"]