ha(H4): repair key_mismatch, диагностика для ESPHome, reconfigure, переводы

- repairs: issue key_mismatch (ERROR, fixable) при состоянии key_error,
  ConfirmRepairFlow, снятие issue при online/unload/remove
- config flow: async_step_reconfigure (меню, prefill ручной формы,
  unique_id_mismatch, update_reload_and_abort) — путь «перепровижинировать»
- diagnostics: config/esp_home (dsn/lanip_key/key_id/host для secrets.yaml)
  + esp_home_masked и redacted entry_data, runtime-снимок значений
  (raw/display) из кэша ядра
- translations: issues.key_mismatch (title/description/fix_flow) en/ru,
  abort unique_id_mismatch/reconfigure_successful; тест согласованности
  strings↔en↔ru
- FglairClient.events_dropped; mock_ac: параметр key_id в фикстуре
- тесты: diagnostics, repairs issue+fix-flow, reconfigure (успех/чужое
  устройство), translations (45 components)
This commit is contained in:
2026-09-29 14:06:39 +03:00
parent dee5819743
commit 57ee555704
15 changed files with 451 additions and 10 deletions
@@ -6,6 +6,7 @@ from unittest.mock import AsyncMock, patch
from helpers import DSN, KEY_ID, LANIP_KEY
from homeassistant import config_entries
from homeassistant.config_entries import SOURCE_RECONFIGURE
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from pytest_homeassistant_custom_component.common import MockConfigEntry
@@ -413,3 +414,68 @@ async def test_import_json_null_device_port(hass: HomeAssistant):
assert result["type"] == "create_entry"
assert result["data"]["device_port"] == 80
assert trial.call_args.args[0]["device_port"] == 80
RECONFIGURE_ENTRY_DATA = {
"host": "127.0.0.1",
"device_port": 9,
"dsn": DSN,
"lanip_key": LANIP_KEY,
"lanip_key_id": KEY_ID,
"name": "Old name",
"model": "AP-WC1E",
"template": "A",
}
async def test_reconfigure_success(hass: HomeAssistant, mock_ac, socket_enabled):
from test_entities import _setup_entry
proc = mock_ac(["--set", "operation_mode=6"])
entry = await _setup_entry(hass, proc.port)
with patch(
"custom_components.fglair.config_flow._run_trial",
return_value=TRIAL_OK,
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_RECONFIGURE, "entry_id": entry.entry_id},
)
assert result["type"] == "menu"
result = await _select(hass, result["flow_id"], "manual")
assert result["type"] == "form"
assert _suggested(result["data_schema"], "host") == "127.0.0.1"
result = await _configure(
hass, result["flow_id"], {**MANUAL_INPUT, "name": "Renamed"}
)
assert result["step_id"] == "preview"
result = await _configure(hass, result["flow_id"], PREVIEW_INPUT)
assert result["type"] == "abort"
assert result["reason"] == "reconfigure_successful"
await hass.async_block_till_done()
assert entry.data["name"] == "Renamed"
assert entry.state.name == "LOADED"
assert await hass.config_entries.async_unload(entry.entry_id)
async def test_reconfigure_wrong_device(hass: HomeAssistant):
entry = MockConfigEntry(
domain=DOMAIN, data=RECONFIGURE_ENTRY_DATA, unique_id=DSN
)
entry.add_to_hass(hass)
with patch(
"custom_components.fglair.config_flow._run_trial",
return_value=TRIAL_OK,
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_RECONFIGURE, "entry_id": entry.entry_id},
)
result = await _select(hass, result["flow_id"], "manual")
result = await _configure(
hass,
result["flow_id"],
{**MANUAL_INPUT, "dsn": "AC000W00OTHER001"},
)
assert result["type"] == "abort"
assert result["reason"] == "unique_id_mismatch"