core/tests/components/openexchangerates/test_config_flow.py

240 lines
7.5 KiB
Python
Raw Normal View History

"""Test the Open Exchange Rates config flow."""
import asyncio
from collections.abc import Generator
from typing import Any
from unittest.mock import AsyncMock, patch
from aioopenexchangerates import (
OpenExchangeRatesAuthError,
OpenExchangeRatesClientError,
)
import pytest
from homeassistant import config_entries
from homeassistant.components.openexchangerates.const import DOMAIN
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from tests.common import MockConfigEntry
@pytest.fixture(name="currencies", autouse=True)
def currencies_fixture(hass: HomeAssistant) -> Generator[AsyncMock, None, None]:
"""Mock currencies."""
with patch(
"homeassistant.components.openexchangerates.config_flow.Client.get_currencies",
return_value={"USD": "United States Dollar", "EUR": "Euro"},
) as mock_currencies:
yield mock_currencies
async def test_user_create_entry(
hass: HomeAssistant,
mock_latest_rates_config_flow: AsyncMock,
mock_setup_entry: AsyncMock,
) -> None:
"""Test we get the form."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == FlowResultType.FORM
assert result["errors"] is None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "test-api-key"},
)
await hass.async_block_till_done()
assert result["type"] == FlowResultType.CREATE_ENTRY
assert result["title"] == "USD"
assert result["data"] == {
"api_key": "test-api-key",
"base": "USD",
}
assert len(mock_setup_entry.mock_calls) == 1
async def test_form_invalid_auth(
hass: HomeAssistant,
mock_latest_rates_config_flow: AsyncMock,
) -> None:
"""Test we handle invalid auth."""
mock_latest_rates_config_flow.side_effect = OpenExchangeRatesAuthError()
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "bad-api-key"},
)
assert result["type"] == FlowResultType.FORM
assert result["errors"] == {"base": "invalid_auth"}
async def test_form_cannot_connect(
hass: HomeAssistant,
mock_latest_rates_config_flow: AsyncMock,
) -> None:
"""Test we handle cannot connect error."""
mock_latest_rates_config_flow.side_effect = OpenExchangeRatesClientError()
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "test-api-key"},
)
assert result["type"] == FlowResultType.FORM
assert result["errors"] == {"base": "cannot_connect"}
async def test_form_unknown_error(
hass: HomeAssistant,
mock_latest_rates_config_flow: AsyncMock,
) -> None:
"""Test we handle unknown error."""
mock_latest_rates_config_flow.side_effect = Exception()
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "test-api-key"},
)
assert result["type"] == FlowResultType.FORM
assert result["errors"] == {"base": "unknown"}
async def test_already_configured_service(
hass: HomeAssistant,
mock_latest_rates_config_flow: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test we abort if the service is already configured."""
mock_config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == FlowResultType.FORM
assert result["errors"] is None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "test-api-key"},
)
assert result["type"] == FlowResultType.ABORT
assert result["reason"] == "already_configured"
async def test_no_currencies(hass: HomeAssistant, currencies: AsyncMock) -> None:
"""Test we abort if the service fails to retrieve currencies."""
currencies.side_effect = OpenExchangeRatesClientError()
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == FlowResultType.ABORT
assert result["reason"] == "cannot_connect"
async def test_currencies_timeout(hass: HomeAssistant, currencies: AsyncMock) -> None:
"""Test we abort if the service times out retrieving currencies."""
async def currencies_side_effect():
await asyncio.sleep(1)
return {"USD": "United States Dollar", "EUR": "Euro"}
currencies.side_effect = currencies_side_effect
with patch(
"homeassistant.components.openexchangerates.config_flow.CLIENT_TIMEOUT", 0
):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == FlowResultType.ABORT
assert result["reason"] == "timeout_connect"
async def test_latest_rates_timeout(
hass: HomeAssistant,
mock_latest_rates_config_flow: AsyncMock,
) -> None:
"""Test we abort if the service times out retrieving latest rates."""
async def latest_rates_side_effect(*args: Any, **kwargs: Any) -> dict[str, float]:
await asyncio.sleep(1)
return {"EUR": 1.0}
mock_latest_rates_config_flow.side_effect = latest_rates_side_effect
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"homeassistant.components.openexchangerates.config_flow.CLIENT_TIMEOUT", 0
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"api_key": "test-api-key"},
)
assert result["type"] == FlowResultType.FORM
assert result["errors"] == {"base": "timeout_connect"}
async def test_reauth(
hass: HomeAssistant,
mock_latest_rates_config_flow: AsyncMock,
mock_setup_entry: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test we can reauthenticate the config entry."""
mock_config_entry.add_to_hass(hass)
flow_context = {
"source": config_entries.SOURCE_REAUTH,
"entry_id": mock_config_entry.entry_id,
"title_placeholders": {"name": mock_config_entry.title},
"unique_id": mock_config_entry.unique_id,
}
result = await hass.config_entries.flow.async_init(
DOMAIN, context=flow_context, data=mock_config_entry.data
)
assert result["type"] == FlowResultType.FORM
assert result["errors"] is None
mock_latest_rates_config_flow.side_effect = OpenExchangeRatesAuthError()
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
"api_key": "invalid-test-api-key",
},
)
assert result["type"] == FlowResultType.FORM
assert result["errors"] == {"base": "invalid_auth"}
mock_latest_rates_config_flow.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
"api_key": "new-test-api-key",
},
)
await hass.async_block_till_done()
assert result["type"] == "abort"
assert result["reason"] == "reauth_successful"
assert len(mock_setup_entry.mock_calls) == 1