mirror of
https://github.com/home-assistant/core.git
synced 2026-05-29 20:23:24 +02:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1aa6e1d32c | |||
| c587e101af | |||
| 6eeeac46f3 | |||
| 86542b8ad0 | |||
| 7e07e7062c | |||
| d7c13fee27 | |||
| a0a44f7a25 |
+1
@@ -57,6 +57,7 @@ OVERKIZ_TO_HVAC_MODE: dict[str, HVACMode] = {
|
||||
OverkizCommandParam.STANDBY: HVACMode.OFF, # main command
|
||||
OverkizCommandParam.AUTO: HVACMode.AUTO,
|
||||
OverkizCommandParam.EXTERNAL: HVACMode.AUTO,
|
||||
OverkizCommandParam.PROG: HVACMode.AUTO,
|
||||
OverkizCommandParam.INTERNAL: HVACMode.AUTO, # main command
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,11 @@ class IRobotEntity(Entity):
|
||||
model=self.vacuum_state.get("sku"),
|
||||
name=str(self.vacuum_state.get("name")),
|
||||
sw_version=self.vacuum_state.get("softwareVer"),
|
||||
hw_version=self.vacuum_state.get("hardwareRev"),
|
||||
hw_version=(
|
||||
str(hw_rev)
|
||||
if (hw_rev := self.vacuum_state.get("hardwareRev")) is not None
|
||||
else None
|
||||
),
|
||||
)
|
||||
|
||||
if mac_address := self.vacuum_state.get("hwPartsRev", {}).get(
|
||||
|
||||
@@ -40,6 +40,8 @@ class TadoConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
login_task: asyncio.Task | None = None
|
||||
refresh_token: str | None = None
|
||||
tado: Tado | None = None
|
||||
tado_device_url: str = ""
|
||||
user_code: str = ""
|
||||
|
||||
async def async_step_reauth(
|
||||
self, entry_data: Mapping[str, Any]
|
||||
@@ -69,8 +71,8 @@ class TadoConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
_LOGGER.exception("Error while initiating Tado")
|
||||
return self.async_abort(reason="cannot_connect")
|
||||
assert self.tado is not None
|
||||
tado_device_url = self.tado.device_verification_url()
|
||||
user_code = URL(tado_device_url).query["user_code"]
|
||||
self.tado_device_url = self.tado.device_verification_url()
|
||||
self.user_code = URL(self.tado_device_url).query["user_code"]
|
||||
|
||||
async def _wait_for_login() -> None:
|
||||
"""Wait for the user to login."""
|
||||
@@ -119,8 +121,8 @@ class TadoConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
step_id="user",
|
||||
progress_action="wait_for_device",
|
||||
description_placeholders={
|
||||
"url": tado_device_url,
|
||||
"code": user_code,
|
||||
"url": self.tado_device_url,
|
||||
"code": self.user_code,
|
||||
},
|
||||
progress_task=self.login_task,
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/thread",
|
||||
"integration_type": "service",
|
||||
"iot_class": "local_polling",
|
||||
"requirements": ["python-otbr-api==2.10.0", "pyroute2==0.7.5"],
|
||||
"requirements": ["python-otbr-api==2.10.0", "pyroute2==0.9.6"],
|
||||
"single_config_entry": true,
|
||||
"zeroconf": ["_meshcop._udp.local."]
|
||||
}
|
||||
|
||||
@@ -468,7 +468,7 @@ class WyomingAssistSatellite(WyomingSatelliteEntity, AssistSatelliteEntity):
|
||||
|
||||
async def on_restart(self) -> None:
|
||||
"""Block until pipeline loop will be restarted."""
|
||||
_LOGGER.warning(
|
||||
_LOGGER.debug(
|
||||
"Satellite has been disconnected. Reconnecting in %s second(s)",
|
||||
_RECONNECT_SECONDS,
|
||||
)
|
||||
|
||||
@@ -138,6 +138,8 @@ SAVE_DELAY = 1
|
||||
|
||||
DISCOVERY_COOLDOWN = 1
|
||||
|
||||
SETUP_RETRY_MAX_WAIT = 600 # 10 minutes
|
||||
|
||||
ISSUE_UNIQUE_ID_COLLISION = "config_entry_unique_id_collision"
|
||||
UNIQUE_ID_COLLISION_TITLE_LIMIT = 5
|
||||
|
||||
@@ -824,7 +826,7 @@ class ConfigEntry[_DataT = Any]:
|
||||
auth_message,
|
||||
)
|
||||
logger.debug("Full exception", exc_info=True)
|
||||
self.async_start_reauth_if_available(hass)
|
||||
self.async_start_reauth(hass)
|
||||
except ConfigEntryNotReady as exc:
|
||||
message = str(exc)
|
||||
error_reason_translation_key = exc.translation_key
|
||||
@@ -836,7 +838,7 @@ class ConfigEntry[_DataT = Any]:
|
||||
error_reason_translation_key,
|
||||
error_reason_translation_placeholders,
|
||||
)
|
||||
wait_time = 2 ** min(self._tries, 4) * 5 + (
|
||||
wait_time = min(2**self._tries * 5, SETUP_RETRY_MAX_WAIT) + (
|
||||
randint(RANDOM_MICROSECOND_MIN, RANDOM_MICROSECOND_MAX) / 1000000
|
||||
)
|
||||
self._tries += 1
|
||||
@@ -1290,19 +1292,6 @@ class ConfigEntry[_DataT = Any]:
|
||||
eager_start=True,
|
||||
)
|
||||
|
||||
@callback
|
||||
def async_start_reauth_if_available(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
context: ConfigFlowContext | None = None,
|
||||
data: dict[str, Any] | None = None,
|
||||
) -> None:
|
||||
"""Start a reauth flow only if the integration implements one."""
|
||||
handler = HANDLERS.get(self.domain)
|
||||
if handler is None or not hasattr(handler, "async_step_reauth"):
|
||||
return
|
||||
self.async_start_reauth(hass, context, data)
|
||||
|
||||
async def _async_init_reauth(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
|
||||
@@ -458,7 +458,7 @@ class DataUpdateCoordinator(BaseDataUpdateCoordinatorProtocol, Generic[_DataT]):
|
||||
raise ConfigEntryAuthFailed from err
|
||||
|
||||
if self.config_entry:
|
||||
self.config_entry.async_start_reauth_if_available(self.hass)
|
||||
self.config_entry.async_start_reauth(self.hass)
|
||||
return
|
||||
|
||||
# Recoverable error
|
||||
@@ -536,7 +536,7 @@ class DataUpdateCoordinator(BaseDataUpdateCoordinatorProtocol, Generic[_DataT]):
|
||||
raise
|
||||
|
||||
if self.config_entry:
|
||||
self.config_entry.async_start_reauth_if_available(self.hass)
|
||||
self.config_entry.async_start_reauth(self.hass)
|
||||
except NotImplementedError as err:
|
||||
self.last_exception = err
|
||||
self.last_update_success = False
|
||||
|
||||
Generated
+1
-1
@@ -2492,7 +2492,7 @@ pyrisco==0.7.0
|
||||
pyrituals==0.0.7
|
||||
|
||||
# homeassistant.components.thread
|
||||
pyroute2==0.7.5
|
||||
pyroute2==0.9.6
|
||||
|
||||
# homeassistant.components.rympro
|
||||
pyrympro==0.0.9
|
||||
|
||||
@@ -1 +1,33 @@
|
||||
"""Tests for the Duco integration."""
|
||||
|
||||
from collections.abc import Sequence
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def setup_integration(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the full Duco integration for testing."""
|
||||
config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
return config_entry
|
||||
|
||||
|
||||
async def setup_platform_integration(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
platforms: Sequence[Platform],
|
||||
) -> MockConfigEntry:
|
||||
"""Set up selected Duco platforms for testing."""
|
||||
config_entry.add_to_hass(hass)
|
||||
with patch("homeassistant.components.duco.PLATFORMS", list(platforms)):
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
return config_entry
|
||||
|
||||
@@ -23,6 +23,8 @@ from homeassistant.components.duco.const import DOMAIN
|
||||
from homeassistant.const import CONF_HOST
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import setup_integration
|
||||
|
||||
from tests.common import MockConfigEntry, load_json_array_fixture
|
||||
|
||||
TEST_HOST = "192.168.1.100"
|
||||
@@ -159,112 +161,7 @@ def mock_lan_info() -> LanInfo:
|
||||
@pytest.fixture
|
||||
def mock_nodes() -> list[Node]:
|
||||
"""Return a list of nodes covering all supported types."""
|
||||
return [
|
||||
Node(
|
||||
node_id=1,
|
||||
general=NodeGeneralInfo(
|
||||
node_type="BOX",
|
||||
sub_type=1,
|
||||
network_type="VIRT",
|
||||
parent=0,
|
||||
asso=0,
|
||||
name="Living",
|
||||
identify=0,
|
||||
),
|
||||
ventilation=NodeVentilationInfo(
|
||||
state="AUTO",
|
||||
time_state_remain=0,
|
||||
time_state_end=0,
|
||||
mode="AUTO",
|
||||
flow_lvl_tgt=0,
|
||||
),
|
||||
sensor=NodeSensorInfo(
|
||||
co2=None,
|
||||
iaq_co2=None,
|
||||
rh=None,
|
||||
iaq_rh=None,
|
||||
temp=27.9,
|
||||
),
|
||||
),
|
||||
Node(
|
||||
node_id=2,
|
||||
general=NodeGeneralInfo(
|
||||
node_type="UCCO2",
|
||||
sub_type=0,
|
||||
network_type="RF",
|
||||
parent=1,
|
||||
asso=1,
|
||||
name="Office CO2",
|
||||
identify=0,
|
||||
),
|
||||
ventilation=NodeVentilationInfo(
|
||||
state="AUTO",
|
||||
time_state_remain=0,
|
||||
time_state_end=0,
|
||||
mode="-",
|
||||
flow_lvl_tgt=None,
|
||||
),
|
||||
sensor=NodeSensorInfo(
|
||||
co2=405,
|
||||
iaq_co2=80,
|
||||
rh=None,
|
||||
iaq_rh=None,
|
||||
temp=19.8,
|
||||
),
|
||||
),
|
||||
Node(
|
||||
node_id=113,
|
||||
general=NodeGeneralInfo(
|
||||
node_type="BSRH",
|
||||
sub_type=0,
|
||||
network_type="RF",
|
||||
parent=1,
|
||||
asso=1,
|
||||
name="Bathroom RH",
|
||||
identify=0,
|
||||
),
|
||||
ventilation=NodeVentilationInfo(
|
||||
state="AUTO",
|
||||
time_state_remain=0,
|
||||
time_state_end=0,
|
||||
mode="-",
|
||||
flow_lvl_tgt=None,
|
||||
),
|
||||
sensor=NodeSensorInfo(
|
||||
co2=None,
|
||||
iaq_co2=None,
|
||||
rh=42.0,
|
||||
iaq_rh=85,
|
||||
temp=27.9,
|
||||
),
|
||||
),
|
||||
Node(
|
||||
node_id=50,
|
||||
general=NodeGeneralInfo(
|
||||
node_type="UCRH",
|
||||
sub_type=0,
|
||||
network_type="RF",
|
||||
parent=1,
|
||||
asso=1,
|
||||
name="Kitchen RH",
|
||||
identify=0,
|
||||
),
|
||||
ventilation=NodeVentilationInfo(
|
||||
state="AUTO",
|
||||
time_state_remain=0,
|
||||
time_state_end=0,
|
||||
mode="-",
|
||||
flow_lvl_tgt=None,
|
||||
),
|
||||
sensor=NodeSensorInfo(
|
||||
co2=None,
|
||||
iaq_co2=None,
|
||||
rh=61.0,
|
||||
iaq_rh=90,
|
||||
temp=22.5,
|
||||
),
|
||||
),
|
||||
]
|
||||
return load_nodes_fixture("nodes.json")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -327,7 +224,4 @@ async def init_integration(
|
||||
mock_duco_client: AsyncMock,
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the Duco integration for testing."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
return mock_config_entry
|
||||
return await setup_integration(hass, mock_config_entry)
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
[
|
||||
{
|
||||
"node_id": 1,
|
||||
"general": {
|
||||
"node_type": "BOX",
|
||||
"sub_type": 1,
|
||||
"network_type": "VIRT",
|
||||
"parent": 0,
|
||||
"asso": 0,
|
||||
"name": "Living",
|
||||
"identify": 0
|
||||
},
|
||||
"ventilation": {
|
||||
"state": "AUTO",
|
||||
"time_state_remain": 0,
|
||||
"time_state_end": 0,
|
||||
"mode": "AUTO",
|
||||
"flow_lvl_tgt": 0
|
||||
},
|
||||
"sensor": {
|
||||
"co2": null,
|
||||
"iaq_co2": null,
|
||||
"rh": null,
|
||||
"iaq_rh": null,
|
||||
"temp": 27.9
|
||||
}
|
||||
},
|
||||
{
|
||||
"node_id": 2,
|
||||
"general": {
|
||||
"node_type": "UCCO2",
|
||||
"sub_type": 0,
|
||||
"network_type": "RF",
|
||||
"parent": 1,
|
||||
"asso": 1,
|
||||
"name": "Office CO2",
|
||||
"identify": 0
|
||||
},
|
||||
"ventilation": {
|
||||
"state": "AUTO",
|
||||
"time_state_remain": 0,
|
||||
"time_state_end": 0,
|
||||
"mode": "-",
|
||||
"flow_lvl_tgt": null
|
||||
},
|
||||
"sensor": {
|
||||
"co2": 405,
|
||||
"iaq_co2": 80,
|
||||
"rh": null,
|
||||
"iaq_rh": null,
|
||||
"temp": 19.8
|
||||
}
|
||||
},
|
||||
{
|
||||
"node_id": 113,
|
||||
"general": {
|
||||
"node_type": "BSRH",
|
||||
"sub_type": 0,
|
||||
"network_type": "RF",
|
||||
"parent": 1,
|
||||
"asso": 1,
|
||||
"name": "Bathroom RH",
|
||||
"identify": 0
|
||||
},
|
||||
"ventilation": {
|
||||
"state": "AUTO",
|
||||
"time_state_remain": 0,
|
||||
"time_state_end": 0,
|
||||
"mode": "-",
|
||||
"flow_lvl_tgt": null
|
||||
},
|
||||
"sensor": {
|
||||
"co2": null,
|
||||
"iaq_co2": null,
|
||||
"rh": 42.0,
|
||||
"iaq_rh": 85,
|
||||
"temp": 27.9
|
||||
}
|
||||
},
|
||||
{
|
||||
"node_id": 50,
|
||||
"general": {
|
||||
"node_type": "UCRH",
|
||||
"sub_type": 0,
|
||||
"network_type": "RF",
|
||||
"parent": 1,
|
||||
"asso": 1,
|
||||
"name": "Kitchen RH",
|
||||
"identify": 0
|
||||
},
|
||||
"ventilation": {
|
||||
"state": "AUTO",
|
||||
"time_state_remain": 0,
|
||||
"time_state_end": 0,
|
||||
"mode": "-",
|
||||
"flow_lvl_tgt": null
|
||||
},
|
||||
"sensor": {
|
||||
"co2": null,
|
||||
"iaq_co2": null,
|
||||
"rh": 61.0,
|
||||
"iaq_rh": 90,
|
||||
"temp": 22.5
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Tests for the Duco fan platform."""
|
||||
|
||||
import logging
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from duco_connectivity import DucoConnectionError, DucoError, DucoRateLimitError
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
@@ -21,6 +21,8 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import setup_platform_integration
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||
|
||||
_FAN_ENTITY = "fan.living"
|
||||
@@ -33,11 +35,7 @@ async def init_integration(
|
||||
mock_duco_client: AsyncMock,
|
||||
) -> MockConfigEntry:
|
||||
"""Set up only the fan platform for testing."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
with patch("homeassistant.components.duco.PLATFORMS", [Platform.FAN]):
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
return mock_config_entry
|
||||
return await setup_platform_integration(hass, mock_config_entry, [Platform.FAN])
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_integration")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Tests for the Duco sensor platform."""
|
||||
|
||||
import logging
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from duco_connectivity import (
|
||||
DucoConnectionError,
|
||||
@@ -22,6 +22,8 @@ from homeassistant.const import STATE_UNAVAILABLE, STATE_UNKNOWN, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
|
||||
from . import setup_platform_integration
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||
|
||||
|
||||
@@ -34,11 +36,7 @@ async def init_integration(
|
||||
) -> MockConfigEntry:
|
||||
"""Set up only the sensor platform for testing."""
|
||||
mock_duco_client.async_get_nodes.return_value = mock_sensor_nodes
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
with patch("homeassistant.components.duco.PLATFORMS", [Platform.SENSOR]):
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
return mock_config_entry
|
||||
return await setup_platform_integration(hass, mock_config_entry, [Platform.SENSOR])
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default", "init_integration")
|
||||
|
||||
@@ -235,7 +235,7 @@ async def test_setup_oauth_reauth_error(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert config_entry.state is ConfigEntryState.SETUP_ERROR
|
||||
mock_async_start_reauth.assert_called_once_with(hass, None, None)
|
||||
mock_async_start_reauth.assert_called_once_with(hass)
|
||||
|
||||
|
||||
async def test_setup_oauth_transient_error(
|
||||
|
||||
@@ -231,6 +231,43 @@ async def test_options_flow(
|
||||
assert result["data"] == {CONF_FALLBACK: CONST_OVERLAY_TADO_DEFAULT}
|
||||
|
||||
|
||||
async def test_show_progress_polling(
|
||||
hass: HomeAssistant,
|
||||
mock_tado_api: MagicMock,
|
||||
mock_setup_entry: AsyncMock,
|
||||
) -> None:
|
||||
"""Test progress step re-entry while login task is still running."""
|
||||
|
||||
event = threading.Event()
|
||||
|
||||
def mock_tado_api_device_activation() -> None:
|
||||
event.wait(timeout=5)
|
||||
|
||||
mock_tado_api.device_activation = mock_tado_api_device_activation
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["type"] is FlowResultType.SHOW_PROGRESS
|
||||
assert result["step_id"] == "user"
|
||||
assert result["description_placeholders"]["url"] is not None
|
||||
assert result["description_placeholders"]["code"] == "TEST"
|
||||
|
||||
# Poll again while task is still running — this re-enters async_step_user
|
||||
# with self.tado already set
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||
assert result["type"] is FlowResultType.SHOW_PROGRESS
|
||||
assert result["description_placeholders"]["url"] is not None
|
||||
assert result["description_placeholders"]["code"] == "TEST"
|
||||
|
||||
# Now complete the login
|
||||
event.set()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
|
||||
|
||||
async def test_homekit(hass: HomeAssistant, mock_tado_api: MagicMock) -> None:
|
||||
"""Test that we abort from homekit if tado is already setup."""
|
||||
|
||||
|
||||
@@ -1702,6 +1702,44 @@ async def test_setup_raise_not_ready(
|
||||
assert entry.reason is None
|
||||
|
||||
|
||||
async def test_setup_not_ready_exponential_backoff(
|
||||
hass: HomeAssistant,
|
||||
manager: config_entries.ConfigEntries,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test setup retry uses exponential backoff capped at 10 minutes."""
|
||||
entry = MockConfigEntry(domain="test")
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
attempts = 0
|
||||
|
||||
async def _mock_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
nonlocal attempts
|
||||
attempts += 1
|
||||
raise ConfigEntryNotReady
|
||||
|
||||
mock_integration(hass, MockModule("test", async_setup_entry=_mock_setup_entry))
|
||||
mock_platform(hass, "test.config_flow", None)
|
||||
|
||||
await manager.async_setup(entry.entry_id)
|
||||
assert attempts == 1
|
||||
|
||||
expected_waits = [5, 10, 20, 40, 80, 160, 320, 600, 600]
|
||||
for i, wait in enumerate(expected_waits):
|
||||
# Advance to just before the retry should fire
|
||||
freezer.tick(wait - 1)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
assert attempts == i + 1, f"Retry {i + 1} fired too early"
|
||||
|
||||
# Advance past the retry point (+ 1s for jitter)
|
||||
freezer.tick(2)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
assert attempts == i + 2, f"Retry {i + 1} did not fire"
|
||||
assert entry.state is config_entries.ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_setup_raise_not_ready_from_exception(
|
||||
hass: HomeAssistant,
|
||||
manager: config_entries.ConfigEntries,
|
||||
@@ -5755,36 +5793,6 @@ async def test_setup_raise_auth_failed_from_future_coordinator_update(
|
||||
assert len(flows) == 1
|
||||
|
||||
|
||||
async def test_setup_raise_auth_failed_without_reauth_flow(
|
||||
hass: HomeAssistant,
|
||||
manager: config_entries.ConfigEntries,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""Test ConfigEntryAuthFailed when the integration has no reauth flow."""
|
||||
entry = MockConfigEntry(title="test_title", domain="test")
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
mock_setup_entry = AsyncMock(
|
||||
side_effect=ConfigEntryAuthFailed("The password is no longer valid")
|
||||
)
|
||||
mock_integration(hass, MockModule("test", async_setup_entry=mock_setup_entry))
|
||||
mock_platform(hass, "test.config_flow", None)
|
||||
|
||||
class NoReauthFlow(config_entries.ConfigFlow):
|
||||
"""Config flow without reauth support."""
|
||||
|
||||
VERSION = 1
|
||||
|
||||
with mock_config_flow("test", NoReauthFlow):
|
||||
await manager.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert "could not authenticate: The password is no longer valid" in caplog.text
|
||||
assert entry.state is config_entries.ConfigEntryState.SETUP_ERROR
|
||||
assert entry.reason == "The password is no longer valid"
|
||||
assert len(hass.config_entries.flow.async_progress()) == 0
|
||||
|
||||
|
||||
async def test_initialize_and_shutdown(hass: HomeAssistant) -> None:
|
||||
"""Test we call the shutdown function at stop."""
|
||||
manager = config_entries.ConfigEntries(hass, {})
|
||||
|
||||
Reference in New Issue
Block a user