diff --git a/homeassistant/components/alexa_devices/__init__.py b/homeassistant/components/alexa_devices/__init__.py index 81d9f09fd682..b04be74029e6 100644 --- a/homeassistant/components/alexa_devices/__init__.py +++ b/homeassistant/components/alexa_devices/__init__.py @@ -1,8 +1,5 @@ """Alexa Devices integration.""" -import asyncio -import contextlib - from homeassistant.const import CONF_COUNTRY, Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import aiohttp_client, config_validation as cv, httpx_client @@ -46,21 +43,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: AmazonConfigEntry) -> bo async def _on_http2_reauth_required() -> None: entry.async_start_reauth(hass) - async def _cancel_http2() -> None: - http2_task.cancel() - with contextlib.suppress(asyncio.CancelledError): - await http2_task - alexa_httpx_client = httpx_client.get_async_client( hass, alpn_protocols=SSL_ALPN_HTTP11_HTTP2, ) - http2_task = await coordinator.api.start_http2_processing( - alexa_httpx_client, on_reauth_required=_on_http2_reauth_required + await coordinator.api.start_http2_processing( + alexa_httpx_client, + on_reauth_required=_on_http2_reauth_required, ) - entry.async_on_unload(_cancel_http2) + entry.async_on_unload(coordinator.api.stop_http2_processing) entry.runtime_data = coordinator diff --git a/tests/components/alexa_devices/conftest.py b/tests/components/alexa_devices/conftest.py index 4f4f9adb90ad..2e6ede4931de 100644 --- a/tests/components/alexa_devices/conftest.py +++ b/tests/components/alexa_devices/conftest.py @@ -65,9 +65,15 @@ def mock_amazon_devices_client() -> Generator[AsyncMock]: client.on_history_event = MagicMock() client.on_volume_state_event = MagicMock() client.on_media_state_event = MagicMock() - http2_task = asyncio.Future() - http2_task.set_result(None) - client.start_http2_processing = AsyncMock(return_value=http2_task) + + async def _start_http2_processing(*_args, **_kwargs) -> asyncio.Task[None]: + async def _completed_task() -> None: + return + + return asyncio.create_task(_completed_task()) + + client.start_http2_processing = AsyncMock(side_effect=_start_http2_processing) + client.stop_http2_processing = AsyncMock() client.send_sound_notification = AsyncMock() yield client diff --git a/tests/components/alexa_devices/test_init.py b/tests/components/alexa_devices/test_init.py index a57181521dca..dff813529d26 100644 --- a/tests/components/alexa_devices/test_init.py +++ b/tests/components/alexa_devices/test_init.py @@ -1,6 +1,7 @@ """Tests for the Alexa Devices integration.""" -from unittest.mock import AsyncMock +import asyncio +from unittest.mock import AsyncMock, patch import pytest from syrupy.assertion import SnapshotAssertion @@ -160,3 +161,47 @@ async def test_http2_reauth_required( flows = hass.config_entries.flow.async_progress() assert len(flows) == 1 assert flows[0]["context"]["source"] == "reauth" + + +async def test_http2_reauth_callback_triggers_reauth( + hass: HomeAssistant, + mock_amazon_devices_client: AsyncMock, + mock_config_entry: MockConfigEntry, +) -> None: + """Test on_reauth_required callback passed to start_http2_processing triggers reauth.""" + captured_callback = None + http2_task: asyncio.Task | None = None + + async def capture_callback(_client, on_reauth_required=None) -> asyncio.Task: + nonlocal captured_callback, http2_task + captured_callback = on_reauth_required + http2_task = hass.loop.create_task(asyncio.sleep(3600)) + return http2_task + + mock_amazon_devices_client.start_http2_processing.side_effect = capture_callback + + with patch.object(mock_config_entry, "async_start_reauth") as mock_reauth: + await setup_integration(hass, mock_config_entry) + + assert captured_callback is not None + await captured_callback() + + mock_reauth.assert_called_once_with(hass) + + assert http2_task is not None + http2_task.cancel() + await asyncio.gather(http2_task, return_exceptions=True) + + +async def test_http2_stop_processing_called_on_unload( + hass: HomeAssistant, + mock_amazon_devices_client: AsyncMock, + mock_config_entry: MockConfigEntry, +) -> None: + """Test stop_http2_processing is called on unload.""" + await setup_integration(hass, mock_config_entry) + + await hass.config_entries.async_unload(mock_config_entry.entry_id) + await hass.async_block_till_done() + + mock_amazon_devices_client.stop_http2_processing.assert_awaited_once()