1
0
mirror of https://github.com/home-assistant/core.git synced 2026-02-15 07:36:16 +00:00

Improve Nintendo Switch parental controls exception handling (#159199)

This commit is contained in:
Jordan Harvey
2025-12-17 06:15:26 +00:00
committed by GitHub
parent 84d7c37502
commit d0c8792e4b
3 changed files with 83 additions and 27 deletions

View File

@@ -5,14 +5,18 @@ from __future__ import annotations
from datetime import timedelta
import logging
from pynintendoauth.exceptions import InvalidOAuthConfigurationException
from pynintendoauth.exceptions import (
HttpException,
InvalidOAuthConfigurationException,
InvalidSessionTokenException,
)
from pynintendoparental import Authenticator, NintendoParental
from pynintendoparental.exceptions import NoDevicesFoundException
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryError
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import DOMAIN
@@ -58,3 +62,13 @@ class NintendoUpdateCoordinator(DataUpdateCoordinator[None]):
translation_domain=DOMAIN,
translation_key="no_devices_found",
) from err
except InvalidSessionTokenException as err:
_LOGGER.debug("Session token invalid, will renew on next update")
raise UpdateFailed from err
except HttpException as err:
if err.error_code == "update_required":
raise ConfigEntryError(
translation_domain=DOMAIN,
translation_key="update_required",
) from err
raise UpdateFailed(retry_after=900) from err

View File

@@ -83,6 +83,9 @@
},
"no_devices_found": {
"message": "No Nintendo devices found for this account."
},
"update_required": {
"message": "The Nintendo Switch parental controls integration requires an update due to changes in Nintendo's API."
}
},
"services": {

View File

@@ -2,8 +2,13 @@
from unittest.mock import AsyncMock
from pynintendoauth.exceptions import InvalidOAuthConfigurationException
from pynintendoauth.exceptions import (
HttpException,
InvalidOAuthConfigurationException,
InvalidSessionTokenException,
)
from pynintendoparental.exceptions import NoDevicesFoundException
import pytest
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
@@ -14,16 +19,62 @@ from . import setup_integration
from tests.common import MockConfigEntry
async def test_invalid_authentication(
@pytest.mark.parametrize(
("exception", "translation_key", "expected_state", "expected_log_message"),
[
(
InvalidOAuthConfigurationException(
status_code=401, message="Authentication failed"
),
"invalid_auth",
ConfigEntryState.SETUP_ERROR,
None,
),
(
NoDevicesFoundException(),
"no_devices_found",
ConfigEntryState.SETUP_ERROR,
None,
),
(
HttpException(
status_code=400, error_code="update_required", message="Update required"
),
"update_required",
ConfigEntryState.SETUP_ERROR,
None,
),
(
HttpException(
status_code=500, error_code="unknown", message="Unknown error"
),
None,
ConfigEntryState.SETUP_RETRY,
None,
),
(
InvalidSessionTokenException(
status_code=403, error_code="invalid_token", message="Invalid token"
),
None,
ConfigEntryState.SETUP_RETRY,
"Session token invalid, will renew on next update",
),
],
)
async def test_update_errors(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_nintendo_client: AsyncMock,
entity_registry: er.EntityRegistry,
caplog: pytest.LogCaptureFixture,
exception: Exception,
translation_key: str,
expected_state: ConfigEntryState,
expected_log_message: str | None,
) -> None:
"""Test handling of invalid authentication."""
mock_nintendo_client.update.side_effect = InvalidOAuthConfigurationException(
status_code=401, message="Authentication failed"
)
"""Test handling of update errors."""
mock_nintendo_client.update.side_effect = exception
await setup_integration(hass, mock_config_entry)
@@ -32,25 +83,13 @@ async def test_invalid_authentication(
entity_registry, mock_config_entry.entry_id
)
assert len(entries) == 0
# Ensure the config entry is marked as error
assert mock_config_entry.state is ConfigEntryState.SETUP_ERROR
# Ensure the config entry is marked as expected state
assert mock_config_entry.state is expected_state
async def test_no_devices(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_nintendo_client: AsyncMock,
entity_registry: er.EntityRegistry,
) -> None:
"""Test handling of invalid authentication."""
mock_nintendo_client.update.side_effect = NoDevicesFoundException()
# Ensure the correct translation key is used in the error
assert mock_config_entry.error_reason_translation_key == translation_key
await setup_integration(hass, mock_config_entry)
# Ensure no entities are created
entries = er.async_entries_for_config_entry(
entity_registry, mock_config_entry.entry_id
)
assert len(entries) == 0
# Ensure the config entry is marked as error
assert mock_config_entry.state is ConfigEntryState.SETUP_ERROR
# If there's an expected log message, check that it was logged
if expected_log_message:
assert expected_log_message in caplog.text