core/tests/components/ituran/test_config_flow.py

255 lines
8.1 KiB
Python

"""Test the Ituran config flow."""
from unittest.mock import AsyncMock
from pyituran.exceptions import IturanApiError, IturanAuthError
import pytest
from homeassistant.components.ituran.const import (
CONF_ID_OR_PASSPORT,
CONF_MOBILE_ID,
CONF_OTP,
CONF_PHONE_NUMBER,
DOMAIN,
)
from homeassistant.config_entries import SOURCE_USER, ConfigFlowResult
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from . import setup_integration
from .const import MOCK_CONFIG_DATA
from tests.common import MockConfigEntry
async def __do_successful_user_step(
hass: HomeAssistant, result: ConfigFlowResult, mock_ituran: AsyncMock
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_ID_OR_PASSPORT: MOCK_CONFIG_DATA[CONF_ID_OR_PASSPORT],
CONF_PHONE_NUMBER: MOCK_CONFIG_DATA[CONF_PHONE_NUMBER],
},
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "otp"
assert result["errors"] == {}
return result
async def __do_successful_otp_step(
hass: HomeAssistant,
result: ConfigFlowResult,
mock_ituran: AsyncMock,
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_OTP: "123456",
},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == f"Ituran {MOCK_CONFIG_DATA[CONF_ID_OR_PASSPORT]}"
assert result["data"][CONF_ID_OR_PASSPORT] == MOCK_CONFIG_DATA[CONF_ID_OR_PASSPORT]
assert result["data"][CONF_PHONE_NUMBER] == MOCK_CONFIG_DATA[CONF_PHONE_NUMBER]
assert result["data"][CONF_MOBILE_ID] is not None
assert result["result"].unique_id == MOCK_CONFIG_DATA[CONF_ID_OR_PASSPORT]
assert len(mock_ituran.is_authenticated.mock_calls) > 0
assert len(mock_ituran.authenticate.mock_calls) > 0
return result
async def test_full_user_flow(
hass: HomeAssistant, mock_ituran: AsyncMock, mock_setup_entry: AsyncMock
) -> None:
"""Test the full user configuration flow."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
result = await __do_successful_user_step(hass, result, mock_ituran)
await __do_successful_otp_step(hass, result, mock_ituran)
async def test_invalid_auth(
hass: HomeAssistant, mock_ituran: AsyncMock, mock_setup_entry: AsyncMock
) -> None:
"""Test invalid credentials configuration flow."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
mock_ituran.request_otp.side_effect = IturanAuthError
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_ID_OR_PASSPORT: MOCK_CONFIG_DATA[CONF_ID_OR_PASSPORT],
CONF_PHONE_NUMBER: MOCK_CONFIG_DATA[CONF_PHONE_NUMBER],
},
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert result["errors"] == {"base": "invalid_auth"}
mock_ituran.request_otp.side_effect = None
result = await __do_successful_user_step(hass, result, mock_ituran)
await __do_successful_otp_step(hass, result, mock_ituran)
async def test_invalid_otp(
hass: HomeAssistant, mock_ituran: AsyncMock, mock_setup_entry: AsyncMock
) -> None:
"""Test invalid OTP configuration flow."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
result = await __do_successful_user_step(hass, result, mock_ituran)
mock_ituran.authenticate.side_effect = IturanAuthError
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_OTP: "123456",
},
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": "invalid_otp"}
mock_ituran.authenticate.side_effect = None
await __do_successful_otp_step(hass, result, mock_ituran)
@pytest.mark.parametrize(
("exception", "expected_error"),
[(IturanApiError, "cannot_connect"), (Exception, "unknown")],
)
async def test_errors(
hass: HomeAssistant,
mock_ituran: AsyncMock,
mock_setup_entry: AsyncMock,
exception: Exception,
expected_error: str,
) -> None:
"""Test connection errors during configuration flow."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
mock_ituran.request_otp.side_effect = exception
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_ID_OR_PASSPORT: MOCK_CONFIG_DATA[CONF_ID_OR_PASSPORT],
CONF_PHONE_NUMBER: MOCK_CONFIG_DATA[CONF_PHONE_NUMBER],
},
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert result["errors"] == {"base": expected_error}
mock_ituran.request_otp.side_effect = None
result = await __do_successful_user_step(hass, result, mock_ituran)
mock_ituran.authenticate.side_effect = exception
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_OTP: "123456",
},
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": expected_error}
mock_ituran.authenticate.side_effect = None
await __do_successful_otp_step(hass, result, mock_ituran)
async def test_already_authenticated(
hass: HomeAssistant, mock_ituran: AsyncMock, mock_setup_entry: AsyncMock
) -> None:
"""Test user already authenticated configuration flow."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
mock_ituran.is_authenticated.return_value = True
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_ID_OR_PASSPORT: MOCK_CONFIG_DATA[CONF_ID_OR_PASSPORT],
CONF_PHONE_NUMBER: MOCK_CONFIG_DATA[CONF_PHONE_NUMBER],
},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == f"Ituran {MOCK_CONFIG_DATA[CONF_ID_OR_PASSPORT]}"
assert result["data"][CONF_ID_OR_PASSPORT] == MOCK_CONFIG_DATA[CONF_ID_OR_PASSPORT]
assert result["data"][CONF_PHONE_NUMBER] == MOCK_CONFIG_DATA[CONF_PHONE_NUMBER]
assert result["data"][CONF_MOBILE_ID] == MOCK_CONFIG_DATA[CONF_MOBILE_ID]
assert result["result"].unique_id == MOCK_CONFIG_DATA[CONF_ID_OR_PASSPORT]
async def test_reauth(
hass: HomeAssistant,
mock_ituran: AsyncMock,
mock_setup_entry: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test reauthenticating."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
result = await __do_successful_user_step(hass, result, mock_ituran)
await __do_successful_otp_step(hass, result, mock_ituran)
await setup_integration(hass, mock_config_entry)
result = await mock_config_entry.start_reauth_flow(hass)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reauth_confirm"
assert result["errors"] is None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={},
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "otp"
assert result["errors"] == {}
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_OTP: "123456",
},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reauth_successful"