core/tests/components/pterodactyl/test_config_flow.py

175 lines
5.6 KiB
Python

"""Test the Pterodactyl config flow."""
from collections.abc import Generator
from unittest.mock import AsyncMock
from pydactyl.exceptions import BadRequestError, PterodactylApiError
import pytest
from requests.exceptions import HTTPError
from requests.models import Response
from homeassistant.components.pterodactyl.const import DOMAIN
from homeassistant.config_entries import SOURCE_USER
from homeassistant.const import CONF_API_KEY, CONF_URL
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from .const import TEST_API_KEY, TEST_URL, TEST_USER_INPUT
from tests.common import MockConfigEntry
def mock_response():
"""Mock HTTP response."""
mock = Response()
mock.status_code = 401
return mock
@pytest.mark.usefixtures("mock_pterodactyl", "mock_setup_entry")
async def test_full_flow(hass: HomeAssistant) -> None:
"""Test full flow without errors."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}
result = await hass.config_entries.flow.async_configure(
flow_id=result["flow_id"],
user_input=TEST_USER_INPUT,
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == TEST_URL
assert result["data"] == TEST_USER_INPUT
@pytest.mark.usefixtures("mock_setup_entry")
@pytest.mark.parametrize(
("exception_type", "expected_error"),
[
(PterodactylApiError, "cannot_connect"),
(BadRequestError, "cannot_connect"),
(Exception, "unknown"),
(HTTPError(response=mock_response()), "invalid_auth"),
],
)
async def test_recovery_after_error(
hass: HomeAssistant,
exception_type: Exception,
expected_error: str,
mock_pterodactyl: Generator[AsyncMock],
) -> None:
"""Test recovery after an error."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}
mock_pterodactyl.client.servers.list_servers.side_effect = exception_type
result = await hass.config_entries.flow.async_configure(
flow_id=result["flow_id"],
user_input=TEST_USER_INPUT,
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": expected_error}
mock_pterodactyl.reset_mock(side_effect=True)
result = await hass.config_entries.flow.async_configure(
flow_id=result["flow_id"], user_input=TEST_USER_INPUT
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == TEST_URL
assert result["data"] == TEST_USER_INPUT
@pytest.mark.usefixtures("mock_setup_entry", "mock_pterodactyl")
async def test_service_already_configured(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test config flow abort if the Pterodactyl server is already configured."""
mock_config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}, data=TEST_USER_INPUT
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
@pytest.mark.usefixtures("mock_pterodactyl", "mock_setup_entry")
async def test_reauth_full_flow(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test reauth config flow success."""
mock_config_entry.add_to_hass(hass)
result = await mock_config_entry.start_reauth_flow(hass)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reauth_confirm"
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_API_KEY: TEST_API_KEY}
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reauth_successful"
assert mock_config_entry.data[CONF_URL] == TEST_URL
assert mock_config_entry.data[CONF_API_KEY] == TEST_API_KEY
@pytest.mark.usefixtures("mock_setup_entry")
@pytest.mark.parametrize(
("exception_type", "expected_error"),
[
(PterodactylApiError, "cannot_connect"),
(BadRequestError, "cannot_connect"),
(Exception, "unknown"),
(HTTPError(response=mock_response()), "invalid_auth"),
],
)
async def test_reauth_recovery_after_error(
hass: HomeAssistant,
exception_type: Exception,
expected_error: str,
mock_config_entry: MockConfigEntry,
mock_pterodactyl: Generator[AsyncMock],
) -> None:
"""Test recovery after an error during re-authentication."""
mock_config_entry.add_to_hass(hass)
result = await mock_config_entry.start_reauth_flow(hass)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reauth_confirm"
mock_pterodactyl.client.servers.list_servers.side_effect = exception_type
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_API_KEY: TEST_API_KEY}
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": expected_error}
mock_pterodactyl.reset_mock(side_effect=True)
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_API_KEY: TEST_API_KEY}
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reauth_successful"
assert mock_config_entry.data[CONF_URL] == TEST_URL
assert mock_config_entry.data[CONF_API_KEY] == TEST_API_KEY