diff --git a/tests/components/homeassistant_hardware/test_config_flow.py b/tests/components/homeassistant_hardware/test_config_flow.py index 2d5067bea3e..427c22fba22 100644 --- a/tests/components/homeassistant_hardware/test_config_flow.py +++ b/tests/components/homeassistant_hardware/test_config_flow.py @@ -19,7 +19,6 @@ from homeassistant.components.homeassistant_hardware.util import ( ApplicationType, FirmwareInfo, get_otbr_addon_manager, - get_zigbee_flasher_addon_manager, ) from homeassistant.config_entries import ConfigEntry, ConfigFlowResult, OptionsFlow from homeassistant.core import HomeAssistant, callback @@ -62,6 +61,18 @@ class FakeFirmwareConfigFlow(BaseFirmwareConfigFlow, domain=TEST_DOMAIN): return await self.async_step_confirm() + async def async_step_install_zigbee_firmware( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + """Install Zigbee firmware.""" + return await self.async_step_confirm_zigbee() + + async def async_step_install_thread_firmware( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + """Install Thread firmware.""" + return await self.async_step_start_otbr_addon() + def _async_flow_finished(self) -> ConfigFlowResult: """Create the config entry.""" assert self._device is not None @@ -160,29 +171,8 @@ def mock_addon_info( update_available=False, version=None, ), - flasher_addon_info: AddonInfo = AddonInfo( - available=True, - hostname=None, - options={}, - state=AddonState.NOT_INSTALLED, - update_available=False, - version=None, - ), ) -> Iterator[tuple[Mock, Mock]]: """Mock the main addon states for the config flow.""" - mock_flasher_manager = Mock(spec_set=get_zigbee_flasher_addon_manager(hass)) - mock_flasher_manager.addon_name = "Silicon Labs Flasher" - mock_flasher_manager.async_start_addon_waiting = AsyncMock( - side_effect=delayed_side_effect() - ) - mock_flasher_manager.async_install_addon_waiting = AsyncMock( - side_effect=delayed_side_effect() - ) - mock_flasher_manager.async_uninstall_addon_waiting = AsyncMock( - side_effect=delayed_side_effect() - ) - mock_flasher_manager.async_get_addon_info.return_value = flasher_addon_info - mock_otbr_manager = Mock(spec_set=get_otbr_addon_manager(hass)) mock_otbr_manager.addon_name = "OpenThread Border Router" mock_otbr_manager.async_install_addon_waiting = AsyncMock( @@ -216,10 +206,6 @@ def mock_addon_info( "homeassistant.components.homeassistant_hardware.util.get_otbr_addon_manager", return_value=mock_otbr_manager, ), - patch( - "homeassistant.components.homeassistant_hardware.firmware_config_flow.get_zigbee_flasher_addon_manager", - return_value=mock_flasher_manager, - ), patch( "homeassistant.components.homeassistant_hardware.firmware_config_flow.is_hassio", return_value=is_hassio, @@ -233,7 +219,7 @@ def mock_addon_info( return_value=firmware_info_result, ), ): - yield mock_otbr_manager, mock_flasher_manager + yield mock_otbr_manager async def test_config_flow_zigbee(hass: HomeAssistant) -> None: @@ -248,7 +234,7 @@ async def test_config_flow_zigbee(hass: HomeAssistant) -> None: with mock_addon_info( hass, app_type=ApplicationType.SPINEL, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: # Pick the menu option: we are now installing the addon result = await hass.config_entries.flow.async_configure( result["flow_id"], @@ -266,16 +252,6 @@ async def test_config_flow_zigbee(hass: HomeAssistant) -> None: assert result["type"] is FlowResultType.SHOW_PROGRESS assert result["step_id"] == "run_zigbee_flasher_addon" assert result["progress_action"] == "run_zigbee_flasher_addon" - assert mock_flasher_manager.async_set_addon_options.mock_calls == [ - call( - { - "device": TEST_DEVICE, - "baudrate": 115200, - "bootloader_baudrate": 115200, - "flow_control": True, - } - ) - ] await hass.async_block_till_done(wait_background_tasks=True) @@ -287,9 +263,6 @@ async def test_config_flow_zigbee(hass: HomeAssistant) -> None: await hass.async_block_till_done(wait_background_tasks=True) - # We are finally done with the addon - assert mock_flasher_manager.async_uninstall_addon_waiting.mock_calls == [call()] - result = await hass.config_entries.flow.async_configure(result["flow_id"]) assert result["type"] is FlowResultType.FORM assert result["step_id"] == "confirm_zigbee" @@ -344,7 +317,7 @@ async def test_config_flow_zigbee_skip_step_if_installed(hass: HomeAssistant) -> update_available=False, version="1.2.3", ), - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: # Pick the menu option: we skip installation, instead we directly run it result = await hass.config_entries.flow.async_configure( result["flow_id"], @@ -419,7 +392,7 @@ async def test_config_flow_thread(hass: HomeAssistant) -> None: with mock_addon_info( hass, app_type=ApplicationType.EZSP, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: # Pick the menu option result = await hass.config_entries.flow.async_configure( result["flow_id"], @@ -507,7 +480,7 @@ async def test_config_flow_thread_addon_already_installed(hass: HomeAssistant) - update_available=False, version=None, ), - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: # Pick the menu option result = await hass.config_entries.flow.async_configure( result["flow_id"], @@ -555,7 +528,7 @@ async def test_config_flow_zigbee_not_hassio(hass: HomeAssistant) -> None: hass, is_hassio=False, app_type=ApplicationType.EZSP, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: result = await hass.config_entries.flow.async_configure( result["flow_id"], user_input={"next_step_id": STEP_PICK_FIRMWARE_ZIGBEE}, @@ -604,7 +577,7 @@ async def test_options_flow_zigbee_to_thread(hass: HomeAssistant) -> None: with mock_addon_info( hass, app_type=ApplicationType.EZSP, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: # First step is confirmation result = await hass.config_entries.options.async_init(config_entry.entry_id) assert result["type"] is FlowResultType.MENU @@ -703,7 +676,7 @@ async def test_options_flow_thread_to_zigbee(hass: HomeAssistant) -> None: with mock_addon_info( hass, app_type=ApplicationType.SPINEL, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: # Pick the menu option: we are now installing the addon result = await hass.config_entries.options.async_configure( result["flow_id"], diff --git a/tests/components/homeassistant_hardware/test_config_flow_failures.py b/tests/components/homeassistant_hardware/test_config_flow_failures.py index 38c2696a62a..1b9b8a7aac9 100644 --- a/tests/components/homeassistant_hardware/test_config_flow_failures.py +++ b/tests/components/homeassistant_hardware/test_config_flow_failures.py @@ -54,7 +54,7 @@ async def test_config_flow_cannot_probe_firmware( with mock_addon_info( hass, app_type=None, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: # Start the flow result = await hass.config_entries.flow.async_init( TEST_DOMAIN, context={"source": "hardware"} @@ -85,7 +85,7 @@ async def test_config_flow_zigbee_not_hassio_wrong_firmware( hass, app_type=ApplicationType.SPINEL, is_hassio=False, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: result = await hass.config_entries.flow.async_configure( result["flow_id"], user_input={} ) @@ -121,7 +121,7 @@ async def test_config_flow_zigbee_flasher_addon_already_running( update_available=False, version="1.0.0", ), - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: result = await hass.config_entries.flow.async_configure( result["flow_id"], user_input={} ) @@ -157,7 +157,7 @@ async def test_config_flow_zigbee_flasher_addon_info_fails(hass: HomeAssistant) update_available=False, version="1.0.0", ), - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: mock_flasher_manager.async_get_addon_info.side_effect = AddonError() result = await hass.config_entries.flow.async_configure( @@ -188,7 +188,7 @@ async def test_config_flow_zigbee_flasher_addon_install_fails( with mock_addon_info( hass, app_type=ApplicationType.SPINEL, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: mock_flasher_manager.async_install_addon_waiting = AsyncMock( side_effect=AddonError() ) @@ -222,7 +222,7 @@ async def test_config_flow_zigbee_flasher_addon_set_config_fails( with mock_addon_info( hass, app_type=ApplicationType.SPINEL, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: mock_flasher_manager.async_install_addon_waiting = AsyncMock( side_effect=delayed_side_effect() ) @@ -258,7 +258,7 @@ async def test_config_flow_zigbee_flasher_run_fails(hass: HomeAssistant) -> None with mock_addon_info( hass, app_type=ApplicationType.SPINEL, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: mock_flasher_manager.async_start_addon_waiting = AsyncMock( side_effect=AddonError() ) @@ -287,7 +287,7 @@ async def test_config_flow_zigbee_flasher_uninstall_fails(hass: HomeAssistant) - with mock_addon_info( hass, app_type=ApplicationType.SPINEL, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: mock_flasher_manager.async_uninstall_addon_waiting = AsyncMock( side_effect=AddonError() ) @@ -326,7 +326,7 @@ async def test_config_flow_zigbee_confirmation_fails(hass: HomeAssistant) -> Non with mock_addon_info( hass, app_type=ApplicationType.EZSP, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: # Pick the menu option: we are now installing the addon result = await hass.config_entries.flow.async_configure( result["flow_id"], @@ -338,7 +338,7 @@ async def test_config_flow_zigbee_confirmation_fails(hass: HomeAssistant) -> Non with mock_addon_info( hass, app_type=None, # Probing fails - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: result = await hass.config_entries.flow.async_configure( result["flow_id"], user_input={} ) @@ -360,7 +360,7 @@ async def test_config_flow_thread_not_hassio(hass: HomeAssistant) -> None: hass, is_hassio=False, app_type=ApplicationType.EZSP, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: result = await hass.config_entries.flow.async_configure( result["flow_id"], user_input={} ) @@ -386,7 +386,7 @@ async def test_config_flow_thread_addon_info_fails(hass: HomeAssistant) -> None: with mock_addon_info( hass, app_type=ApplicationType.EZSP, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: mock_otbr_manager.async_get_addon_info.side_effect = AddonError() result = await hass.config_entries.flow.async_configure( result["flow_id"], user_input={} @@ -422,7 +422,7 @@ async def test_config_flow_thread_addon_already_running(hass: HomeAssistant) -> update_available=False, version="1.0.0", ), - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: mock_otbr_manager.async_install_addon_waiting = AsyncMock( side_effect=AddonError() ) @@ -453,7 +453,7 @@ async def test_config_flow_thread_addon_install_fails(hass: HomeAssistant) -> No with mock_addon_info( hass, app_type=ApplicationType.EZSP, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: mock_otbr_manager.async_install_addon_waiting = AsyncMock( side_effect=AddonError() ) @@ -484,7 +484,7 @@ async def test_config_flow_thread_addon_set_config_fails(hass: HomeAssistant) -> with mock_addon_info( hass, app_type=ApplicationType.EZSP, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: mock_otbr_manager.async_set_addon_options = AsyncMock(side_effect=AddonError()) result = await hass.config_entries.flow.async_configure( @@ -515,7 +515,7 @@ async def test_config_flow_thread_flasher_run_fails(hass: HomeAssistant) -> None with mock_addon_info( hass, app_type=ApplicationType.EZSP, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: mock_otbr_manager.async_start_addon_waiting = AsyncMock( side_effect=AddonError() ) @@ -543,7 +543,7 @@ async def test_config_flow_thread_flasher_uninstall_fails(hass: HomeAssistant) - with mock_addon_info( hass, app_type=ApplicationType.EZSP, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: mock_otbr_manager.async_uninstall_addon_waiting = AsyncMock( side_effect=AddonError() ) @@ -580,7 +580,7 @@ async def test_config_flow_thread_confirmation_fails(hass: HomeAssistant) -> Non with mock_addon_info( hass, app_type=ApplicationType.EZSP, - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: result = await hass.config_entries.flow.async_configure( result["flow_id"], user_input={} ) @@ -601,7 +601,7 @@ async def test_config_flow_thread_confirmation_fails(hass: HomeAssistant) -> Non with mock_addon_info( hass, app_type=None, # Probing fails - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: result = await hass.config_entries.flow.async_configure( result["flow_id"], user_input={} ) @@ -694,7 +694,7 @@ async def test_options_flow_thread_to_zigbee_otbr_configured( update_available=False, version="1.0.0", ), - ) as (mock_otbr_manager, mock_flasher_manager): + ) as mock_otbr_manager: result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={"next_step_id": STEP_PICK_FIRMWARE_ZIGBEE}, diff --git a/tests/components/homeassistant_hardware/test_update.py b/tests/components/homeassistant_hardware/test_update.py index 23d1e546791..6dd32281286 100644 --- a/tests/components/homeassistant_hardware/test_update.py +++ b/tests/components/homeassistant_hardware/test_update.py @@ -6,7 +6,7 @@ import asyncio from collections.abc import AsyncGenerator import dataclasses import logging -from unittest.mock import AsyncMock, Mock, patch +from unittest.mock import Mock, patch import aiohttp from ha_silabs_firmware_client import FirmwareManifest, FirmwareMetadata @@ -353,10 +353,14 @@ async def test_update_entity_installation( "https://example.org/release_notes" ) - mock_firmware = Mock() - mock_flasher = AsyncMock() - - async def mock_flash_firmware(fw_image, progress_callback): + async def mock_flash_firmware( + hass: HomeAssistant, + device: str, + fw_data: bytes, + expected_installed_firmware_type: ApplicationType, + bootloader_reset_type: str | None = None, + progress_callback: Callable[[int, int], None] | None = None, + ) -> FirmwareInfo: await asyncio.sleep(0) progress_callback(0, 100) await asyncio.sleep(0) @@ -364,31 +368,20 @@ async def test_update_entity_installation( await asyncio.sleep(0) progress_callback(100, 100) - mock_flasher.flash_firmware = mock_flash_firmware + return FirmwareInfo( + device=TEST_DEVICE, + firmware_type=ApplicationType.EZSP, + firmware_version="7.4.4.0 build 0", + owners=[], + source="probe", + ) # When we install it, the other integration is reloaded with ( patch( - "homeassistant.components.homeassistant_hardware.update.parse_firmware_image", - return_value=mock_firmware, + "homeassistant.components.homeassistant_hardware.update.async_flash_silabs_firmware", + side_effect=mock_flash_firmware, ), - patch( - "homeassistant.components.homeassistant_hardware.update.Flasher", - return_value=mock_flasher, - ), - patch( - "homeassistant.components.homeassistant_hardware.update.probe_silabs_firmware_info", - return_value=FirmwareInfo( - device=TEST_DEVICE, - firmware_type=ApplicationType.EZSP, - firmware_version="7.4.4.0 build 0", - owners=[], - source="probe", - ), - ), - patch.object( - owning_config_entry, "async_unload", wraps=owning_config_entry.async_unload - ) as owning_config_entry_unload, ): state_changes: list[Event[EventStateChangedData]] = async_capture_events( hass, EVENT_STATE_CHANGED @@ -421,9 +414,6 @@ async def test_update_entity_installation( assert state_changes[6].data["new_state"].attributes["update_percentage"] is None assert state_changes[6].data["new_state"].attributes["in_progress"] is False - # The owning integration was unloaded and is again running - assert len(owning_config_entry_unload.mock_calls) == 1 - # After the firmware update, the entity has the new version and the correct state state_after_install = hass.states.get(TEST_UPDATE_ENTITY_ID) assert state_after_install is not None @@ -454,19 +444,10 @@ async def test_update_entity_installation_failure( assert state_before_install.attributes["installed_version"] == "7.3.1.0" assert state_before_install.attributes["latest_version"] == "7.4.4.0" - mock_flasher = AsyncMock() - mock_flasher.flash_firmware.side_effect = RuntimeError( - "Something broke during flashing!" - ) - with ( patch( - "homeassistant.components.homeassistant_hardware.update.parse_firmware_image", - return_value=Mock(), - ), - patch( - "homeassistant.components.homeassistant_hardware.update.Flasher", - return_value=mock_flasher, + "homeassistant.components.homeassistant_hardware.update.async_flash_silabs_firmware", + side_effect=HomeAssistantError("Failed to flash firmware"), ), pytest.raises(HomeAssistantError, match="Failed to flash firmware"), ): @@ -509,16 +490,10 @@ async def test_update_entity_installation_probe_failure( with ( patch( - "homeassistant.components.homeassistant_hardware.update.parse_firmware_image", - return_value=Mock(), - ), - patch( - "homeassistant.components.homeassistant_hardware.update.Flasher", - return_value=AsyncMock(), - ), - patch( - "homeassistant.components.homeassistant_hardware.update.probe_silabs_firmware_info", - return_value=None, + "homeassistant.components.homeassistant_hardware.update.async_flash_silabs_firmware", + side_effect=HomeAssistantError( + "Failed to probe the firmware after flashing" + ), ), pytest.raises( HomeAssistantError, match="Failed to probe the firmware after flashing"