mirror of
https://github.com/home-assistant/core.git
synced 2025-08-02 12:15:08 +02:00
Fix hardware unit tests
This commit is contained in:
@@ -24,7 +24,6 @@ from homeassistant.core import callback
|
|||||||
from homeassistant.data_entry_flow import AbortFlow
|
from homeassistant.data_entry_flow import AbortFlow
|
||||||
from homeassistant.helpers.hassio import is_hassio
|
from homeassistant.helpers.hassio import is_hassio
|
||||||
|
|
||||||
from . import silabs_multiprotocol_addon
|
|
||||||
from .const import OTBR_DOMAIN, ZHA_DOMAIN
|
from .const import OTBR_DOMAIN, ZHA_DOMAIN
|
||||||
from .util import (
|
from .util import (
|
||||||
ApplicationType,
|
ApplicationType,
|
||||||
@@ -76,22 +75,6 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
|
|
||||||
return placeholders
|
return placeholders
|
||||||
|
|
||||||
async def _async_set_addon_config(
|
|
||||||
self, config: dict, addon_manager: AddonManager
|
|
||||||
) -> None:
|
|
||||||
"""Set add-on config."""
|
|
||||||
try:
|
|
||||||
await addon_manager.async_set_addon_options(config)
|
|
||||||
except AddonError as err:
|
|
||||||
_LOGGER.error(err)
|
|
||||||
raise AbortFlow(
|
|
||||||
"addon_set_config_failed",
|
|
||||||
description_placeholders={
|
|
||||||
**self._get_translation_placeholders(),
|
|
||||||
"addon_name": addon_manager.addon_name,
|
|
||||||
},
|
|
||||||
) from err
|
|
||||||
|
|
||||||
async def _async_get_addon_info(self, addon_manager: AddonManager) -> AddonInfo:
|
async def _async_get_addon_info(self, addon_manager: AddonManager) -> AddonInfo:
|
||||||
"""Return add-on info."""
|
"""Return add-on info."""
|
||||||
try:
|
try:
|
||||||
@@ -174,46 +157,6 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
"""Install Zigbee firmware."""
|
"""Install Zigbee firmware."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
async def _install_addon(
|
|
||||||
self,
|
|
||||||
addon_manager: silabs_multiprotocol_addon.WaitingAddonManager,
|
|
||||||
step_id: str,
|
|
||||||
next_step_id: str,
|
|
||||||
) -> ConfigFlowResult:
|
|
||||||
"""Show progress dialog for installing an addon."""
|
|
||||||
addon_info = await self._async_get_addon_info(addon_manager)
|
|
||||||
|
|
||||||
_LOGGER.debug("Flasher addon state: %s", addon_info)
|
|
||||||
|
|
||||||
if not self.addon_install_task:
|
|
||||||
self.addon_install_task = self.hass.async_create_task(
|
|
||||||
addon_manager.async_install_addon_waiting(),
|
|
||||||
"Addon install",
|
|
||||||
)
|
|
||||||
|
|
||||||
if not self.addon_install_task.done():
|
|
||||||
return self.async_show_progress(
|
|
||||||
step_id=step_id,
|
|
||||||
progress_action="install_addon",
|
|
||||||
description_placeholders={
|
|
||||||
**self._get_translation_placeholders(),
|
|
||||||
"addon_name": addon_manager.addon_name,
|
|
||||||
},
|
|
||||||
progress_task=self.addon_install_task,
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
|
||||||
await self.addon_install_task
|
|
||||||
except AddonError as err:
|
|
||||||
_LOGGER.error(err)
|
|
||||||
self._failed_addon_name = addon_manager.addon_name
|
|
||||||
self._failed_addon_reason = "addon_install_failed"
|
|
||||||
return self.async_show_progress_done(next_step_id="addon_operation_failed")
|
|
||||||
finally:
|
|
||||||
self.addon_install_task = None
|
|
||||||
|
|
||||||
return self.async_show_progress_done(next_step_id=next_step_id)
|
|
||||||
|
|
||||||
async def async_step_addon_operation_failed(
|
async def async_step_addon_operation_failed(
|
||||||
self, user_input: dict[str, Any] | None = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> ConfigFlowResult:
|
) -> ConfigFlowResult:
|
||||||
@@ -311,12 +254,40 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
self, user_input: dict[str, Any] | None = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> ConfigFlowResult:
|
) -> ConfigFlowResult:
|
||||||
"""Show progress dialog for installing the OTBR addon."""
|
"""Show progress dialog for installing the OTBR addon."""
|
||||||
return await self._install_addon(
|
addon_manager = get_otbr_addon_manager(self.hass)
|
||||||
addon_manager=get_otbr_addon_manager(self.hass),
|
addon_info = await self._async_get_addon_info(addon_manager)
|
||||||
step_id="install_otbr_addon",
|
|
||||||
next_step_id="pick_firmware_thread",
|
_LOGGER.debug("OTBR addon info: %s", addon_info)
|
||||||
|
|
||||||
|
if not self.addon_install_task:
|
||||||
|
self.addon_install_task = self.hass.async_create_task(
|
||||||
|
addon_manager.async_install_addon_waiting(),
|
||||||
|
"OTBR addon install",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not self.addon_install_task.done():
|
||||||
|
return self.async_show_progress(
|
||||||
|
step_id="install_otbr_addon",
|
||||||
|
progress_action="install_addon",
|
||||||
|
description_placeholders={
|
||||||
|
**self._get_translation_placeholders(),
|
||||||
|
"addon_name": addon_manager.addon_name,
|
||||||
|
},
|
||||||
|
progress_task=self.addon_install_task,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
await self.addon_install_task
|
||||||
|
except AddonError as err:
|
||||||
|
_LOGGER.error(err)
|
||||||
|
self._failed_addon_name = addon_manager.addon_name
|
||||||
|
self._failed_addon_reason = "addon_install_failed"
|
||||||
|
return self.async_show_progress_done(next_step_id="addon_operation_failed")
|
||||||
|
finally:
|
||||||
|
self.addon_install_task = None
|
||||||
|
|
||||||
|
return self.async_show_progress_done(next_step_id="pick_firmware_thread")
|
||||||
|
|
||||||
async def async_step_start_otbr_addon(
|
async def async_step_start_otbr_addon(
|
||||||
self, user_input: dict[str, Any] | None = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> ConfigFlowResult:
|
) -> ConfigFlowResult:
|
||||||
@@ -334,7 +305,18 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
}
|
}
|
||||||
|
|
||||||
_LOGGER.debug("Reconfiguring OTBR addon with %s", new_addon_config)
|
_LOGGER.debug("Reconfiguring OTBR addon with %s", new_addon_config)
|
||||||
await self._async_set_addon_config(new_addon_config, otbr_manager)
|
|
||||||
|
try:
|
||||||
|
await otbr_manager.async_set_addon_options(new_addon_config)
|
||||||
|
except AddonError as err:
|
||||||
|
_LOGGER.error(err)
|
||||||
|
raise AbortFlow(
|
||||||
|
"addon_set_config_failed",
|
||||||
|
description_placeholders={
|
||||||
|
**self._get_translation_placeholders(),
|
||||||
|
"addon_name": otbr_manager.addon_name,
|
||||||
|
},
|
||||||
|
) from err
|
||||||
|
|
||||||
if not self.addon_start_task:
|
if not self.addon_start_task:
|
||||||
self.addon_start_task = self.hass.async_create_task(
|
self.addon_start_task = self.hass.async_create_task(
|
||||||
|
@@ -163,7 +163,7 @@ async def test_config_flow_thread_addon_info_fails(hass: HomeAssistant) -> None:
|
|||||||
"ignore_translations_for_mock_domains",
|
"ignore_translations_for_mock_domains",
|
||||||
["test_firmware_domain"],
|
["test_firmware_domain"],
|
||||||
)
|
)
|
||||||
async def test_config_flow_thread_addon_already_running(hass: HomeAssistant) -> None:
|
async def test_config_flow_thread_addon_already_configured(hass: HomeAssistant) -> None:
|
||||||
"""Test failure case when the Thread addon is already running."""
|
"""Test failure case when the Thread addon is already running."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
TEST_DOMAIN, context={"source": "hardware"}
|
TEST_DOMAIN, context={"source": "hardware"}
|
||||||
@@ -175,7 +175,9 @@ async def test_config_flow_thread_addon_already_running(hass: HomeAssistant) ->
|
|||||||
otbr_addon_info=AddonInfo(
|
otbr_addon_info=AddonInfo(
|
||||||
available=True,
|
available=True,
|
||||||
hostname=None,
|
hostname=None,
|
||||||
options={},
|
options={
|
||||||
|
"device": TEST_DEVICE + "2", # A different device
|
||||||
|
},
|
||||||
state=AddonState.RUNNING,
|
state=AddonState.RUNNING,
|
||||||
update_available=False,
|
update_available=False,
|
||||||
version="1.0.0",
|
version="1.0.0",
|
||||||
@@ -235,7 +237,7 @@ async def test_config_flow_thread_addon_install_fails(hass: HomeAssistant) -> No
|
|||||||
)
|
)
|
||||||
async def test_config_flow_thread_addon_set_config_fails(hass: HomeAssistant) -> None:
|
async def test_config_flow_thread_addon_set_config_fails(hass: HomeAssistant) -> None:
|
||||||
"""Test failure case when flasher addon cannot be configured."""
|
"""Test failure case when flasher addon cannot be configured."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
init_result = await hass.config_entries.flow.async_init(
|
||||||
TEST_DOMAIN, context={"source": "hardware"}
|
TEST_DOMAIN, context={"source": "hardware"}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -243,21 +245,33 @@ async def test_config_flow_thread_addon_set_config_fails(hass: HomeAssistant) ->
|
|||||||
hass,
|
hass,
|
||||||
app_type=ApplicationType.EZSP,
|
app_type=ApplicationType.EZSP,
|
||||||
) as mock_otbr_manager:
|
) as mock_otbr_manager:
|
||||||
|
|
||||||
|
async def install_addon() -> None:
|
||||||
|
mock_otbr_manager.async_get_addon_info.return_value = AddonInfo(
|
||||||
|
available=True,
|
||||||
|
hostname=None,
|
||||||
|
options={"device": TEST_DEVICE},
|
||||||
|
state=AddonState.NOT_RUNNING,
|
||||||
|
update_available=False,
|
||||||
|
version="1.0.0",
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_otbr_manager.async_install_addon_waiting = AsyncMock(
|
||||||
|
side_effect=install_addon
|
||||||
|
)
|
||||||
mock_otbr_manager.async_set_addon_options = AsyncMock(side_effect=AddonError())
|
mock_otbr_manager.async_set_addon_options = AsyncMock(side_effect=AddonError())
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
confirm_result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={}
|
init_result["flow_id"], user_input={}
|
||||||
)
|
)
|
||||||
result = await hass.config_entries.flow.async_configure(
|
|
||||||
result["flow_id"],
|
pick_thread_result = await hass.config_entries.flow.async_configure(
|
||||||
|
confirm_result["flow_id"],
|
||||||
user_input={"next_step_id": STEP_PICK_FIRMWARE_THREAD},
|
user_input={"next_step_id": STEP_PICK_FIRMWARE_THREAD},
|
||||||
)
|
)
|
||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
|
||||||
await hass.async_block_till_done(wait_background_tasks=True)
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
assert pick_thread_result["type"] == FlowResultType.ABORT
|
||||||
assert result["type"] == FlowResultType.ABORT
|
assert pick_thread_result["reason"] == "addon_set_config_failed"
|
||||||
assert result["reason"] == "addon_set_config_failed"
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
@@ -266,63 +280,35 @@ async def test_config_flow_thread_addon_set_config_fails(hass: HomeAssistant) ->
|
|||||||
)
|
)
|
||||||
async def test_config_flow_thread_flasher_run_fails(hass: HomeAssistant) -> None:
|
async def test_config_flow_thread_flasher_run_fails(hass: HomeAssistant) -> None:
|
||||||
"""Test failure case when flasher addon fails to run."""
|
"""Test failure case when flasher addon fails to run."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
init_result = await hass.config_entries.flow.async_init(
|
||||||
TEST_DOMAIN, context={"source": "hardware"}
|
TEST_DOMAIN, context={"source": "hardware"}
|
||||||
)
|
)
|
||||||
|
|
||||||
with mock_addon_info(
|
with mock_addon_info(
|
||||||
hass,
|
hass,
|
||||||
app_type=ApplicationType.EZSP,
|
app_type=ApplicationType.EZSP,
|
||||||
|
otbr_addon_info=AddonInfo(
|
||||||
|
available=True,
|
||||||
|
hostname=None,
|
||||||
|
options={"device": TEST_DEVICE},
|
||||||
|
state=AddonState.NOT_RUNNING,
|
||||||
|
update_available=False,
|
||||||
|
version="1.0.0",
|
||||||
|
),
|
||||||
) as mock_otbr_manager:
|
) as mock_otbr_manager:
|
||||||
mock_otbr_manager.async_start_addon_waiting = AsyncMock(
|
mock_otbr_manager.async_start_addon_waiting = AsyncMock(
|
||||||
side_effect=AddonError()
|
side_effect=AddonError()
|
||||||
)
|
)
|
||||||
result = await hass.config_entries.flow.async_configure(
|
confirm_result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={}
|
init_result["flow_id"], user_input={}
|
||||||
)
|
)
|
||||||
result = await hass.config_entries.flow.async_configure(
|
pick_thread_result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
confirm_result["flow_id"],
|
||||||
user_input={"next_step_id": STEP_PICK_FIRMWARE_THREAD},
|
user_input={"next_step_id": STEP_PICK_FIRMWARE_THREAD},
|
||||||
)
|
)
|
||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
|
||||||
await hass.async_block_till_done(wait_background_tasks=True)
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
assert pick_thread_result["type"] == FlowResultType.ABORT
|
||||||
assert result["type"] == FlowResultType.ABORT
|
assert pick_thread_result["reason"] == "addon_start_failed"
|
||||||
assert result["reason"] == "addon_start_failed"
|
|
||||||
|
|
||||||
|
|
||||||
async def test_config_flow_thread_flasher_uninstall_fails(hass: HomeAssistant) -> None:
|
|
||||||
"""Test failure case when flasher addon uninstall fails."""
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
|
||||||
TEST_DOMAIN, context={"source": "hardware"}
|
|
||||||
)
|
|
||||||
|
|
||||||
with mock_addon_info(
|
|
||||||
hass,
|
|
||||||
app_type=ApplicationType.EZSP,
|
|
||||||
) as mock_otbr_manager:
|
|
||||||
mock_otbr_manager.async_uninstall_addon_waiting = AsyncMock(
|
|
||||||
side_effect=AddonError()
|
|
||||||
)
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
|
||||||
result["flow_id"], user_input={}
|
|
||||||
)
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
|
||||||
result["flow_id"],
|
|
||||||
user_input={"next_step_id": STEP_PICK_FIRMWARE_THREAD},
|
|
||||||
)
|
|
||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
|
||||||
await hass.async_block_till_done(wait_background_tasks=True)
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
|
||||||
await hass.async_block_till_done(wait_background_tasks=True)
|
|
||||||
|
|
||||||
# Uninstall failure isn't critical
|
|
||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
|
||||||
assert result["type"] is FlowResultType.FORM
|
|
||||||
assert result["step_id"] == "confirm_otbr"
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
@@ -331,40 +317,49 @@ async def test_config_flow_thread_flasher_uninstall_fails(hass: HomeAssistant) -
|
|||||||
)
|
)
|
||||||
async def test_config_flow_thread_confirmation_fails(hass: HomeAssistant) -> None:
|
async def test_config_flow_thread_confirmation_fails(hass: HomeAssistant) -> None:
|
||||||
"""Test the config flow failing due to OpenThread firmware not being detected."""
|
"""Test the config flow failing due to OpenThread firmware not being detected."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
init_result = await hass.config_entries.flow.async_init(
|
||||||
TEST_DOMAIN, context={"source": "hardware"}
|
TEST_DOMAIN, context={"source": "hardware"}
|
||||||
)
|
)
|
||||||
|
|
||||||
with mock_addon_info(
|
with mock_addon_info(
|
||||||
hass,
|
hass,
|
||||||
app_type=ApplicationType.EZSP,
|
app_type=ApplicationType.EZSP,
|
||||||
|
otbr_addon_info=AddonInfo(
|
||||||
|
available=True,
|
||||||
|
hostname=None,
|
||||||
|
options={"device": TEST_DEVICE},
|
||||||
|
state=AddonState.RUNNING,
|
||||||
|
update_available=False,
|
||||||
|
version="1.0.0",
|
||||||
|
),
|
||||||
):
|
):
|
||||||
result = await hass.config_entries.flow.async_configure(
|
confirm_result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={}
|
init_result["flow_id"], user_input={}
|
||||||
)
|
)
|
||||||
result = await hass.config_entries.flow.async_configure(
|
pick_thread_result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
confirm_result["flow_id"],
|
||||||
user_input={"next_step_id": STEP_PICK_FIRMWARE_THREAD},
|
user_input={"next_step_id": STEP_PICK_FIRMWARE_THREAD},
|
||||||
)
|
)
|
||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
install_progress_result = await hass.config_entries.flow.async_configure(
|
||||||
|
pick_thread_result["flow_id"]
|
||||||
|
)
|
||||||
await hass.async_block_till_done(wait_background_tasks=True)
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
confirm_result = await hass.config_entries.flow.async_configure(
|
||||||
await hass.async_block_till_done(wait_background_tasks=True)
|
install_progress_result["flow_id"]
|
||||||
|
)
|
||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
assert confirm_result["type"] is FlowResultType.FORM
|
||||||
assert result["type"] is FlowResultType.FORM
|
assert confirm_result["step_id"] == "confirm_otbr"
|
||||||
assert result["step_id"] == "confirm_otbr"
|
|
||||||
|
|
||||||
with mock_addon_info(
|
with mock_addon_info(
|
||||||
hass,
|
hass,
|
||||||
app_type=None, # Probing fails
|
app_type=None, # Probing fails
|
||||||
):
|
):
|
||||||
result = await hass.config_entries.flow.async_configure(
|
error_result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input={}
|
confirm_result["flow_id"], user_input={}
|
||||||
)
|
)
|
||||||
assert result["type"] is FlowResultType.ABORT
|
assert error_result["type"] is FlowResultType.ABORT
|
||||||
assert result["reason"] == "unsupported_firmware"
|
assert error_result["reason"] == "unsupported_firmware"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
Reference in New Issue
Block a user