"""Test the Vilfo Router config flow.""" from typing import Any from unittest.mock import AsyncMock import pytest from vilfo.exceptions import AuthenticationException, VilfoException from homeassistant.components.vilfo.const import DOMAIN from homeassistant.config_entries import SOURCE_USER from homeassistant.const import CONF_ACCESS_TOKEN, CONF_HOST from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType from tests.common import MockConfigEntry @pytest.mark.parametrize( ("user_input", "expected_unique_id", "mac"), [ ( {CONF_HOST: "testadmin.vilfo.com", CONF_ACCESS_TOKEN: "test-token"}, "testadmin.vilfo.com", None, ), ( {CONF_HOST: "testadmin.vilfo.com", CONF_ACCESS_TOKEN: "test-token"}, "FF-00-00-00-00-00", "FF-00-00-00-00-00", ), ( {CONF_HOST: "192.168.0.1", CONF_ACCESS_TOKEN: "test-token"}, "FF-00-00-00-00-00", "FF-00-00-00-00-00", ), ( {CONF_HOST: "2001:db8::1428:57ab", CONF_ACCESS_TOKEN: "test-token"}, "FF-00-00-00-00-00", "FF-00-00-00-00-00", ), ], ) async def test_full_flow( hass: HomeAssistant, mock_vilfo_client: AsyncMock, mock_setup_entry: AsyncMock, mock_is_valid_host: AsyncMock, user_input: dict[str, Any], expected_unique_id: str, mac: str | None, ) -> None: """Test we can finish a config flow.""" mock_vilfo_client.resolve_mac_address.return_value = mac mock_vilfo_client.mac = mac result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER} ) await hass.async_block_till_done() assert result["type"] is FlowResultType.FORM assert not result["errors"] result = await hass.config_entries.flow.async_configure( result["flow_id"], user_input, ) await hass.async_block_till_done() assert result["type"] is FlowResultType.CREATE_ENTRY assert result["title"] == user_input[CONF_HOST] assert result["data"] == user_input assert result["result"].unique_id == expected_unique_id assert len(mock_setup_entry.mock_calls) == 1 async def test_form_invalid_auth( hass: HomeAssistant, mock_vilfo_client: AsyncMock, mock_is_valid_host: AsyncMock, mock_setup_entry: AsyncMock, ) -> None: """Test we handle invalid auth.""" mock_vilfo_client.get_board_information.side_effect = AuthenticationException mock_vilfo_client.resolve_mac_address.return_value = None result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER} ) await hass.async_block_till_done() assert result["type"] is FlowResultType.FORM assert not result["errors"] result = await hass.config_entries.flow.async_configure( result["flow_id"], {CONF_HOST: "testadmin.vilfo.com", CONF_ACCESS_TOKEN: "test-token"}, ) await hass.async_block_till_done() assert result["type"] is FlowResultType.FORM assert result["errors"] == {"base": "invalid_auth"} mock_vilfo_client.get_board_information.side_effect = None mock_vilfo_client.resolve_mac_address.return_value = "FF-00-00-00-00-00" result = await hass.config_entries.flow.async_configure( result["flow_id"], {CONF_HOST: "testadmin.vilfo.com", CONF_ACCESS_TOKEN: "test-token"}, ) await hass.async_block_till_done() assert result["type"] is FlowResultType.CREATE_ENTRY @pytest.mark.parametrize( ("side_effect", "error"), [(VilfoException, "cannot_connect"), (Exception, "unknown")], ) async def test_form_exceptions( hass: HomeAssistant, mock_vilfo_client: AsyncMock, mock_is_valid_host: AsyncMock, mock_setup_entry: AsyncMock, side_effect: Exception, error: str, ) -> None: """Test we handle exceptions.""" mock_vilfo_client.ping.side_effect = side_effect result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER} ) result = await hass.config_entries.flow.async_configure( result["flow_id"], {CONF_HOST: "testadmin.vilfo.com", CONF_ACCESS_TOKEN: "test-token"}, ) assert result["type"] is FlowResultType.FORM assert result["errors"] == {"base": error} mock_vilfo_client.ping.side_effect = None result = await hass.config_entries.flow.async_configure( result["flow_id"], {CONF_HOST: "testadmin.vilfo.com", CONF_ACCESS_TOKEN: "test-token"}, ) await hass.async_block_till_done() assert result["type"] is FlowResultType.CREATE_ENTRY async def test_form_wrong_host( hass: HomeAssistant, mock_is_valid_host: AsyncMock, ) -> None: """Test we handle wrong host errors.""" mock_is_valid_host.return_value = False result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER}, data={ CONF_HOST: "this is an invalid hostname", CONF_ACCESS_TOKEN: "test-token", }, ) assert result["errors"] == {"host": "wrong_host"} async def test_form_already_configured( hass: HomeAssistant, mock_vilfo_client: AsyncMock, mock_setup_entry: AsyncMock, mock_config_entry: MockConfigEntry, mock_is_valid_host: AsyncMock, ) -> None: """Test that we handle already configured exceptions appropriately.""" mock_config_entry.add_to_hass(hass) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER} ) await hass.async_block_till_done() result = await hass.config_entries.flow.async_configure( result["flow_id"], {CONF_HOST: "testadmin.vilfo.com", CONF_ACCESS_TOKEN: "test-token"}, ) await hass.async_block_till_done() assert result["type"] is FlowResultType.ABORT assert result["reason"] == "already_configured"