From 2d0c4e4a591737a18696fe74740027aa6dcce161 Mon Sep 17 00:00:00 2001 From: Noah Husby <32528627+noahhusby@users.noreply.github.com> Date: Thu, 12 Dec 2024 01:56:29 -0500 Subject: [PATCH] Improve config flow test coverage for Russound RIO (#132981) --- .../russound_rio/quality_scale.yaml | 5 +--- tests/components/russound_rio/__init__.py | 12 ++++++++ .../russound_rio/test_config_flow.py | 29 +++++++++++++++++++ tests/components/russound_rio/test_init.py | 26 +++++++++++++++-- .../russound_rio/test_media_player.py | 10 ++----- 5 files changed, 68 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/russound_rio/quality_scale.yaml b/homeassistant/components/russound_rio/quality_scale.yaml index aaa354b2b31..2d396892aa8 100644 --- a/homeassistant/components/russound_rio/quality_scale.yaml +++ b/homeassistant/components/russound_rio/quality_scale.yaml @@ -10,10 +10,7 @@ rules: This integration uses a push API. No polling required. brands: done common-modules: done - config-flow-test-coverage: - status: todo - comment: | - Missing unique_id check in test_form() and test_import(). Test for adding same device twice missing. + config-flow-test-coverage: done config-flow: done dependency-transparency: done docs-actions: diff --git a/tests/components/russound_rio/__init__.py b/tests/components/russound_rio/__init__.py index d0e6d77f1ee..d8764285dd3 100644 --- a/tests/components/russound_rio/__init__.py +++ b/tests/components/russound_rio/__init__.py @@ -1,5 +1,9 @@ """Tests for the Russound RIO integration.""" +from unittest.mock import AsyncMock + +from aiorussound.models import CallbackType + from homeassistant.core import HomeAssistant from tests.common import MockConfigEntry @@ -11,3 +15,11 @@ async def setup_integration(hass: HomeAssistant, config_entry: MockConfigEntry) await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() + + +async def mock_state_update( + client: AsyncMock, callback_type: CallbackType = CallbackType.STATE +) -> None: + """Trigger a callback in the media player.""" + for callback in client.register_state_update_callbacks.call_args_list: + await callback[0][0](client, callback_type) diff --git a/tests/components/russound_rio/test_config_flow.py b/tests/components/russound_rio/test_config_flow.py index cf754852731..28cbf7eda5e 100644 --- a/tests/components/russound_rio/test_config_flow.py +++ b/tests/components/russound_rio/test_config_flow.py @@ -9,6 +9,8 @@ from homeassistant.data_entry_flow import FlowResultType from .const import MOCK_CONFIG, MODEL +from tests.common import MockConfigEntry + async def test_form( hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_russound_client: AsyncMock @@ -29,6 +31,7 @@ async def test_form( assert result["title"] == MODEL assert result["data"] == MOCK_CONFIG assert len(mock_setup_entry.mock_calls) == 1 + assert result["result"].unique_id == "00:11:22:33:44:55" async def test_form_cannot_connect( @@ -60,6 +63,31 @@ async def test_form_cannot_connect( assert len(mock_setup_entry.mock_calls) == 1 +async def test_duplicate( + hass: HomeAssistant, + mock_russound_client: AsyncMock, + mock_setup_entry: AsyncMock, + mock_config_entry: MockConfigEntry, +) -> None: + """Test duplicate flow.""" + mock_config_entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": SOURCE_USER}, + ) + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "user" + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + MOCK_CONFIG, + ) + + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "already_configured" + + async def test_import( hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_russound_client: AsyncMock ) -> None: @@ -74,6 +102,7 @@ async def test_import( assert result["title"] == MODEL assert result["data"] == MOCK_CONFIG assert len(mock_setup_entry.mock_calls) == 1 + assert result["result"].unique_id == "00:11:22:33:44:55" async def test_import_cannot_connect( diff --git a/tests/components/russound_rio/test_init.py b/tests/components/russound_rio/test_init.py index 6787ee37c79..e7022fa6ac1 100644 --- a/tests/components/russound_rio/test_init.py +++ b/tests/components/russound_rio/test_init.py @@ -1,7 +1,9 @@ """Tests for the Russound RIO integration.""" -from unittest.mock import AsyncMock +from unittest.mock import AsyncMock, Mock +from aiorussound.models import CallbackType +import pytest from syrupy import SnapshotAssertion from homeassistant.components.russound_rio.const import DOMAIN @@ -9,7 +11,7 @@ from homeassistant.config_entries import ConfigEntryState from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr -from . import setup_integration +from . import mock_state_update, setup_integration from tests.common import MockConfigEntry @@ -42,3 +44,23 @@ async def test_device_info( ) assert device_entry is not None assert device_entry == snapshot + + +async def test_disconnect_reconnect_log( + hass: HomeAssistant, + snapshot: SnapshotAssertion, + mock_russound_client: AsyncMock, + mock_config_entry: MockConfigEntry, + device_registry: dr.DeviceRegistry, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test device registry integration.""" + await setup_integration(hass, mock_config_entry) + + mock_russound_client.is_connected = Mock(return_value=False) + await mock_state_update(mock_russound_client, CallbackType.CONNECTION) + assert "Disconnected from device at 127.0.0.1" in caplog.text + + mock_russound_client.is_connected = Mock(return_value=True) + await mock_state_update(mock_russound_client, CallbackType.CONNECTION) + assert "Reconnected to device at 127.0.0.1" in caplog.text diff --git a/tests/components/russound_rio/test_media_player.py b/tests/components/russound_rio/test_media_player.py index e720e2c7f65..c740ec4f39e 100644 --- a/tests/components/russound_rio/test_media_player.py +++ b/tests/components/russound_rio/test_media_player.py @@ -2,7 +2,7 @@ from unittest.mock import AsyncMock -from aiorussound.models import CallbackType, PlayStatus +from aiorussound.models import PlayStatus import pytest from homeassistant.const import ( @@ -15,18 +15,12 @@ from homeassistant.const import ( ) from homeassistant.core import HomeAssistant -from . import setup_integration +from . import mock_state_update, setup_integration from .const import ENTITY_ID_ZONE_1 from tests.common import MockConfigEntry -async def mock_state_update(client: AsyncMock) -> None: - """Trigger a callback in the media player.""" - for callback in client.register_state_update_callbacks.call_args_list: - await callback[0][0](client, CallbackType.STATE) - - @pytest.mark.parametrize( ("zone_status", "source_play_status", "media_player_state"), [