Files
fgl-aircon/tests/components/fglair/test_repairs.py
T
petr.polezhaev 43d3ff7dea ha(H4): исправления по ревью — маскировка ключа в дампе, reload-repair, reconfigure сохраняет поля
- major: diagnostics больше не содержит полный lanip_key (esp_home —
  маска, entry_data redacted); ключ для ESPHome — через reconfigure/CLI;
  план §3 синхронизирован; дамп при незагруженной записи не падает
- reconfigure: сохраняет listen_port/keepalive_ms и текущие overrides/
  temp_step; превью-дефолты подхватывают значения записи
- repair fix-flow: подтверждение перезагружает запись (issue снимается
  только когда сессия вышла из key_error; иначе создаётся заново)
- key_issue_id helper, использование async_remove_issue (мёртвый код),
  CONF_EMAIL/PASSWORD в TO_REDACT, placeholders в fix_flow, тест
  плейсхолдеров ru
- тесты обновлены (47 components)
2026-09-29 14:29:36 +03:00

107 lines
4.0 KiB
Python

"""Repair issue при несовпадении LAN-ключа и его fix-flow."""
from __future__ import annotations
import asyncio
import time
from helpers import DSN, KEY_ID
from homeassistant.core import HomeAssistant
from homeassistant.helpers import issue_registry as ir
from homeassistant.setup import async_setup_component
from test_entities import _setup_entry
from custom_components.fglair.const import DOMAIN
from pyfglair import State
async def _wait_for(predicate, timeout: float = 20.0):
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
result = predicate()
if result:
return result
await asyncio.sleep(0.1)
raise AssertionError("условие не выполнено за отведённое время")
async def test_key_error_creates_and_fixes_issue(
hass: HomeAssistant, mock_ac, socket_enabled
):
assert await async_setup_component(hass, "repairs", {})
proc = mock_ac([], key_id=KEY_ID + 1)
entry = await _setup_entry(hass, proc.port)
runtime = entry.runtime_data
await _wait_for(lambda: runtime.client.state == State.KEY_ERROR)
registry = ir.async_get(hass)
issue_id = f"key_mismatch_{DSN}"
issue = registry.async_get_issue(DOMAIN, issue_id)
assert issue is not None
assert issue.is_fixable
assert issue.translation_key == "key_mismatch"
assert issue.translation_placeholders["device"] == "Mock AC"
flow_manager = hass.data["repairs"]["flow_manager"]
result = await flow_manager.async_init(DOMAIN, data={"issue_id": issue_id})
assert result["type"] == "form"
result = await flow_manager.async_configure(result["flow_id"], {})
assert result["type"] == "create_entry"
await hass.async_block_till_done()
# Ключ всё ещё неверен: после reload issue создан снова, а не потерян.
assert registry.async_get_issue(DOMAIN, issue_id) is not None
await hass.config_entries.async_unload(entry.entry_id)
async def test_reconfigure_fixes_key_error(
hass: HomeAssistant, mock_ac, socket_enabled
):
"""Repair-путь целиком: bad key_id → issue → reconfigure → online → issue снят."""
from homeassistant.config_entries import SOURCE_RECONFIGURE
from test_config_flow import MANUAL_INPUT, PREVIEW_INPUT
proc = mock_ac(
["--set", "operation_mode=6"], key_id=KEY_ID + 1
)
entry = await _setup_entry(hass, proc.port)
runtime = entry.runtime_data
await _wait_for(lambda: runtime.client.state == State.KEY_ERROR)
registry = ir.async_get(hass)
issue_id = f"key_mismatch_{DSN}"
assert registry.async_get_issue(DOMAIN, issue_id) is not None
# Mock помнит только один app_addr; останавливаем «залипшую» сессию,
# чтобы пробная сессия config flow получила KE (штатно это делает reload).
await runtime.client.async_stop()
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_RECONFIGURE, "entry_id": entry.entry_id},
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {"next_step_id": "manual"}
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
**MANUAL_INPUT,
"host": "127.0.0.1",
"device_port": proc.port,
"lanip_key_id": KEY_ID + 1,
},
)
assert result["step_id"] == "preview", result.get("errors")
result = await hass.config_entries.flow.async_configure(
result["flow_id"], PREVIEW_INPUT
)
assert result["type"] == "abort"
assert result["reason"] == "reconfigure_successful"
await hass.async_block_till_done()
runtime = entry.runtime_data
await _wait_for(lambda: runtime.client.state == State.ONLINE)
assert registry.async_get_issue(DOMAIN, issue_id) is None
assert entry.data["lanip_key_id"] == KEY_ID + 1
assert await hass.config_entries.async_unload(entry.entry_id)