mirror of https://github.com/home-assistant/core
363 lines
12 KiB
Python
363 lines
12 KiB
Python
"""Test the MyPermobil config flow."""
|
|
|
|
from unittest.mock import Mock, patch
|
|
|
|
from mypermobil import (
|
|
MyPermobilAPIException,
|
|
MyPermobilClientException,
|
|
MyPermobilEulaException,
|
|
)
|
|
import pytest
|
|
|
|
from homeassistant import config_entries
|
|
from homeassistant.components.permobil import config_flow
|
|
from homeassistant.const import CONF_CODE, CONF_EMAIL, CONF_REGION, CONF_TOKEN, CONF_TTL
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.data_entry_flow import FlowResultType
|
|
|
|
from .const import MOCK_REGION_NAME, MOCK_TOKEN, MOCK_URL
|
|
|
|
from tests.common import MockConfigEntry
|
|
|
|
pytestmark = pytest.mark.usefixtures("mock_setup_entry")
|
|
|
|
MOCK_CODE = "012345"
|
|
MOCK_EMAIL = "valid@email.com"
|
|
INVALID_EMAIL = "this is not a valid email"
|
|
VALID_DATA = {
|
|
CONF_EMAIL: MOCK_EMAIL,
|
|
CONF_REGION: MOCK_URL,
|
|
CONF_CODE: MOCK_CODE,
|
|
CONF_TOKEN: MOCK_TOKEN[0],
|
|
CONF_TTL: MOCK_TOKEN[1],
|
|
}
|
|
|
|
|
|
async def test_sucessful_config_flow(hass: HomeAssistant, my_permobil: Mock) -> None:
|
|
"""Test the config flow from start to finish with no errors."""
|
|
# init flow
|
|
with patch(
|
|
"homeassistant.components.permobil.config_flow.MyPermobil",
|
|
return_value=my_permobil,
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
config_flow.DOMAIN,
|
|
context={"source": config_entries.SOURCE_USER},
|
|
data={CONF_EMAIL: MOCK_EMAIL},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "region"
|
|
assert result["errors"] == {}
|
|
|
|
# select region step
|
|
result = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
user_input={CONF_REGION: MOCK_REGION_NAME},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "email_code"
|
|
assert result["errors"] == {}
|
|
# request region code
|
|
result = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
user_input={CONF_CODE: MOCK_CODE},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
|
assert result["data"] == VALID_DATA
|
|
|
|
|
|
async def test_config_flow_incorrect_code(
|
|
hass: HomeAssistant, my_permobil: Mock
|
|
) -> None:
|
|
"""Test email code verification with API error.
|
|
|
|
Test the config flow from start to until email code verification
|
|
and have the API return API error.
|
|
"""
|
|
my_permobil.request_application_token.side_effect = MyPermobilAPIException
|
|
# init flow
|
|
with patch(
|
|
"homeassistant.components.permobil.config_flow.MyPermobil",
|
|
return_value=my_permobil,
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
config_flow.DOMAIN,
|
|
context={"source": config_entries.SOURCE_USER},
|
|
data={CONF_EMAIL: MOCK_EMAIL},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "region"
|
|
assert result["errors"] == {}
|
|
|
|
# select region step
|
|
result = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
user_input={CONF_REGION: MOCK_REGION_NAME},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "email_code"
|
|
assert result["errors"] == {}
|
|
|
|
# request region code
|
|
# here the request_application_token raises a MyPermobilAPIException
|
|
result = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
user_input={CONF_CODE: MOCK_CODE},
|
|
)
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "email_code"
|
|
assert result["errors"]["base"] == "invalid_code"
|
|
|
|
|
|
async def test_config_flow_unsigned_eula(
|
|
hass: HomeAssistant, my_permobil: Mock
|
|
) -> None:
|
|
"""Test email code verification with unsigned eula error.
|
|
|
|
Test the config flow from start to until email code verification
|
|
and have the API return that the eula is unsigned.
|
|
"""
|
|
my_permobil.request_application_token.side_effect = MyPermobilEulaException
|
|
# init flow
|
|
with patch(
|
|
"homeassistant.components.permobil.config_flow.MyPermobil",
|
|
return_value=my_permobil,
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
config_flow.DOMAIN,
|
|
context={"source": config_entries.SOURCE_USER},
|
|
data={CONF_EMAIL: MOCK_EMAIL},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "region"
|
|
assert result["errors"] == {}
|
|
|
|
# select region step
|
|
result = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
user_input={CONF_REGION: MOCK_REGION_NAME},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "email_code"
|
|
assert result["errors"] == {}
|
|
|
|
# request region code
|
|
# here the request_application_token raises a MyPermobilEulaException
|
|
result = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
user_input={CONF_CODE: MOCK_CODE},
|
|
)
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "email_code"
|
|
assert result["errors"]["base"] == "unsigned_eula"
|
|
|
|
# Retry to submit the code again, but this time the user has signed the EULA
|
|
with patch.object(
|
|
my_permobil,
|
|
"request_application_token",
|
|
return_value=MOCK_TOKEN,
|
|
):
|
|
result = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
user_input={CONF_CODE: MOCK_CODE},
|
|
)
|
|
|
|
# Now the method should not raise an exception, and you can proceed with your assertions
|
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
|
assert result["data"] == VALID_DATA
|
|
|
|
|
|
async def test_config_flow_incorrect_region(
|
|
hass: HomeAssistant, my_permobil: Mock
|
|
) -> None:
|
|
"""Test when the user does not exist in the selected region.
|
|
|
|
Test the config flow from start to until the request for email
|
|
code and have the API return error because there is not user for
|
|
that email.
|
|
"""
|
|
my_permobil.request_application_code.side_effect = MyPermobilAPIException
|
|
# init flow
|
|
with patch(
|
|
"homeassistant.components.permobil.config_flow.MyPermobil",
|
|
return_value=my_permobil,
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
config_flow.DOMAIN,
|
|
context={"source": config_entries.SOURCE_USER},
|
|
data={CONF_EMAIL: MOCK_EMAIL},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "region"
|
|
assert result["errors"] == {}
|
|
|
|
# select region step
|
|
# here the request_application_code raises a MyPermobilAPIException
|
|
result = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
user_input={CONF_REGION: MOCK_REGION_NAME},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "region"
|
|
assert result["errors"]["base"] == "code_request_error"
|
|
|
|
|
|
async def test_config_flow_region_request_error(
|
|
hass: HomeAssistant, my_permobil: Mock
|
|
) -> None:
|
|
"""Test region request error.
|
|
|
|
Test the config flow from start to until the request for regions
|
|
and have the API return an error.
|
|
"""
|
|
my_permobil.request_region_names.side_effect = MyPermobilAPIException
|
|
# init flow
|
|
# here the request_region_names raises a MyPermobilAPIException
|
|
with patch(
|
|
"homeassistant.components.permobil.config_flow.MyPermobil",
|
|
return_value=my_permobil,
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
config_flow.DOMAIN,
|
|
context={"source": config_entries.SOURCE_USER},
|
|
data={CONF_EMAIL: MOCK_EMAIL},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "region"
|
|
assert result["errors"]["base"] == "region_fetch_error"
|
|
|
|
|
|
async def test_config_flow_invalid_email(
|
|
hass: HomeAssistant, my_permobil: Mock
|
|
) -> None:
|
|
"""Test an incorrectly formatted email.
|
|
|
|
Test that the email must be formatted correctly. The schema for the
|
|
input should already check for this, but since the API does a
|
|
separate check that might not overlap 100% with the schema,
|
|
this test is still needed.
|
|
"""
|
|
my_permobil.set_email.side_effect = MyPermobilClientException()
|
|
# init flow
|
|
# here the set_email raises a MyPermobilClientException
|
|
with patch(
|
|
"homeassistant.components.permobil.config_flow.MyPermobil",
|
|
return_value=my_permobil,
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
config_flow.DOMAIN,
|
|
context={"source": config_entries.SOURCE_USER},
|
|
data={CONF_EMAIL: INVALID_EMAIL},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == config_entries.SOURCE_USER
|
|
assert result["errors"]["base"] == "invalid_email"
|
|
|
|
|
|
async def test_config_flow_reauth_success(
|
|
hass: HomeAssistant, my_permobil: Mock
|
|
) -> None:
|
|
"""Test the config flow reauth make sure that the values are replaced."""
|
|
# new token and code
|
|
reauth_token = ("b" * 256, "reauth_date")
|
|
reauth_code = "567890"
|
|
my_permobil.request_application_token.return_value = reauth_token
|
|
|
|
mock_entry = MockConfigEntry(
|
|
domain="permobil",
|
|
data=VALID_DATA,
|
|
)
|
|
mock_entry.add_to_hass(hass)
|
|
|
|
with patch(
|
|
"homeassistant.components.permobil.config_flow.MyPermobil",
|
|
return_value=my_permobil,
|
|
):
|
|
result = await mock_entry.start_reauth_flow(hass)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "email_code"
|
|
assert result["errors"] == {}
|
|
|
|
# request new token
|
|
result = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
user_input={CONF_CODE: reauth_code},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.ABORT
|
|
assert result["reason"] == "reauth_successful"
|
|
assert mock_entry.data == {
|
|
CONF_EMAIL: MOCK_EMAIL,
|
|
CONF_REGION: MOCK_URL,
|
|
CONF_CODE: reauth_code,
|
|
CONF_TOKEN: reauth_token[0],
|
|
CONF_TTL: reauth_token[1],
|
|
}
|
|
|
|
|
|
async def test_config_flow_reauth_fail_invalid_code(
|
|
hass: HomeAssistant, my_permobil: Mock
|
|
) -> None:
|
|
"""Test the config flow reauth when the email code fails."""
|
|
# new code
|
|
reauth_invalid_code = "567890" # pretend this code is invalid/incorrect
|
|
my_permobil.request_application_token.side_effect = MyPermobilAPIException
|
|
mock_entry = MockConfigEntry(
|
|
domain="permobil",
|
|
data=VALID_DATA,
|
|
)
|
|
mock_entry.add_to_hass(hass)
|
|
|
|
with patch(
|
|
"homeassistant.components.permobil.config_flow.MyPermobil",
|
|
return_value=my_permobil,
|
|
):
|
|
result = await mock_entry.start_reauth_flow(hass)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "email_code"
|
|
assert result["errors"] == {}
|
|
|
|
# request request new token but have the API return error
|
|
result = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"],
|
|
user_input={CONF_CODE: reauth_invalid_code},
|
|
)
|
|
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "email_code"
|
|
assert result["errors"]["base"] == "invalid_code"
|
|
|
|
|
|
async def test_config_flow_reauth_fail_code_request(
|
|
hass: HomeAssistant, my_permobil: Mock
|
|
) -> None:
|
|
"""Test the config flow reauth."""
|
|
my_permobil.request_application_code.side_effect = MyPermobilAPIException
|
|
mock_entry = MockConfigEntry(
|
|
domain="permobil",
|
|
data=VALID_DATA,
|
|
)
|
|
mock_entry.add_to_hass(hass)
|
|
# test the reauth and have request_application_code fail leading to an abort
|
|
with patch(
|
|
"homeassistant.components.permobil.config_flow.MyPermobil",
|
|
return_value=my_permobil,
|
|
):
|
|
result = await mock_entry.start_reauth_flow(hass)
|
|
|
|
assert result["type"] is FlowResultType.ABORT
|
|
assert result["reason"] == "unknown"
|