"""Config flow fglair: меню, ручной ввод, импорт, облако (discover замокан).""" from __future__ import annotations import json from unittest.mock import AsyncMock, patch from helpers import DSN, KEY_ID, LANIP_KEY from homeassistant import config_entries from homeassistant.core import HomeAssistant from pytest_homeassistant_custom_component.common import MockConfigEntry import pyfglair from custom_components.fglair.const import DOMAIN from custom_components.fglair.trial import TrialResult from pyfglair.provision import Device MANUAL_INPUT = { "host": "192.168.1.50", "device_port": 80, "dsn": DSN, "lanip_key": LANIP_KEY, "lanip_key_id": KEY_ID, "name": "Bedroom", "model": "AP-WC1E", } TRIAL_OK = TrialResult(ok=True) TRIAL_NETWORK_FAIL = TrialResult(ok=False, reason="unreachable") async def _menu(hass: HomeAssistant): return await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) async def _select(hass: HomeAssistant, flow_id: str, option: str): return await hass.config_entries.flow.async_configure( flow_id, {"next_step_id": option} ) async def test_user_menu(hass: HomeAssistant): result = await _menu(hass) assert result["type"] == "menu" assert set(result["menu_options"]) == {"cloud", "manual", "import_json"} async def test_manual_success(hass: HomeAssistant): with patch( "custom_components.fglair.config_flow._run_trial", return_value=TRIAL_OK, ) as trial: result = await _menu(hass) result = await _select(hass, result["flow_id"], "manual") assert result["type"] == "form" result = await hass.config_entries.flow.async_configure( result["flow_id"], MANUAL_INPUT ) assert result["type"] == "create_entry" assert result["title"] == "Bedroom" assert result["result"].unique_id == DSN data = result["data"] assert data["lanip_key_id"] == KEY_ID assert data["template"] == "A" trial.assert_called_once() assert trial.call_args.args[0]["host"] == "192.168.1.50" async def test_manual_connect_error(hass: HomeAssistant): with patch( "custom_components.fglair.config_flow._run_trial", return_value=TRIAL_NETWORK_FAIL, ): result = await _menu(hass) result = await _select(hass, result["flow_id"], "manual") result = await hass.config_entries.flow.async_configure( result["flow_id"], MANUAL_INPUT ) assert result["type"] == "form" assert result["errors"] == {"base": "cannot_connect"} async def test_manual_key_mismatch_error(hass: HomeAssistant): with patch( "custom_components.fglair.config_flow._run_trial", return_value=TrialResult(ok=False, reason="key_mismatch"), ): result = await _menu(hass) result = await _select(hass, result["flow_id"], "manual") result = await hass.config_entries.flow.async_configure( result["flow_id"], MANUAL_INPUT ) assert result["type"] == "form" assert result["errors"] == {"base": "key_mismatch"} async def test_manual_already_configured(hass: HomeAssistant): existing = MockConfigEntry(domain=DOMAIN, data={}, unique_id=DSN) existing.add_to_hass(hass) with patch( "custom_components.fglair.config_flow._run_trial", return_value=TRIAL_OK, ): result = await _menu(hass) result = await _select(hass, result["flow_id"], "manual") result = await hass.config_entries.flow.async_configure( result["flow_id"], MANUAL_INPUT ) assert result["type"] == "abort" assert result["reason"] == "already_configured" async def test_import_json_success(hass: HomeAssistant): payload = json.dumps( { "ip_address": "192.168.1.60", "dsn": DSN, "lanip_key": LANIP_KEY, "lanip_key_id": KEY_ID, "model": "AP-WB2E", "name": "Kitchen", } ) with patch( "custom_components.fglair.config_flow._run_trial", return_value=TRIAL_OK, ): result = await _menu(hass) result = await _select(hass, result["flow_id"], "import_json") assert result["type"] == "form" result = await hass.config_entries.flow.async_configure( result["flow_id"], {"config_json": payload} ) assert result["type"] == "create_entry" assert result["data"]["host"] == "192.168.1.60" assert result["data"]["template"] == "B" async def test_import_json_invalid(hass: HomeAssistant): result = await _menu(hass) result = await _select(hass, result["flow_id"], "import_json") result = await hass.config_entries.flow.async_configure( result["flow_id"], {"config_json": "not json"} ) assert result["type"] == "form" assert result["errors"] == {"base": "invalid_import"} async def test_cloud_flow_success(hass: HomeAssistant): device = Device( name="Bedroom", model="AP-WC1E", dsn=DSN, lan_ip="192.168.1.50", lanip_key=LANIP_KEY, lanip_key_id=KEY_ID, region="eu", ) with patch( "pyfglair.discover", AsyncMock(return_value=[device]) ), patch( "custom_components.fglair.config_flow._run_trial", return_value=TRIAL_OK, ): result = await _menu(hass) result = await _select(hass, result["flow_id"], "cloud") assert result["type"] == "form" result = await hass.config_entries.flow.async_configure( result["flow_id"], {"email": "user@example.com", "password": "secret", "region": "eu"}, ) assert result["type"] == "form" assert result["step_id"] == "cloud_device" with patch( "custom_components.fglair.config_flow._run_trial", return_value=TRIAL_OK, ): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"dsn": DSN} ) assert result["type"] == "create_entry" assert result["data"]["host"] == "192.168.1.50" assert result["data"]["lanip_key_id"] == KEY_ID async def test_cloud_auth_error(hass: HomeAssistant): with patch( "pyfglair.discover", AsyncMock(side_effect=pyfglair.ProvisionError("Ошибка входа (401)")), ): result = await _menu(hass) result = await _select(hass, result["flow_id"], "cloud") result = await hass.config_entries.flow.async_configure( result["flow_id"], {"email": "user@example.com", "password": "bad", "region": "eu"}, ) assert result["type"] == "form" assert result["errors"] == {"base": "invalid_auth"}