Files
core/tests/components/gatus/test_config_flow.py
T
2026-07-17 11:31:36 +02:00

218 lines
7.0 KiB
Python

"""Test the Gatus Config flow."""
from unittest.mock import AsyncMock
from gatus_api import GatusClientError
import pytest
from homeassistant import config_entries
from homeassistant.components.gatus.const import DOMAIN
from homeassistant.const import CONF_URL
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from tests.common import MockConfigEntry
@pytest.mark.usefixtures("mock_gatus_client")
async def test_form_success(hass: HomeAssistant, mock_setup_entry: AsyncMock) -> None:
"""Test we get the form, validate the client, and create a successful entry."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_URL: "http://gatus.example.com:8080"},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Gatus"
assert result["data"] == {
CONF_URL: "http://gatus.example.com:8080",
}
assert len(mock_setup_entry.mock_calls) == 1
@pytest.mark.usefixtures("mock_gatus_client")
async def test_form_success_with_path(
hass: HomeAssistant, mock_setup_entry: AsyncMock
) -> None:
"""Test we get the form, validate the client, and create a successful entry with a sub-path."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_URL: "http://gatus.example.com:8080/gatus-instance/"},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Gatus"
assert result["data"] == {
CONF_URL: "http://gatus.example.com:8080/gatus-instance",
}
assert len(mock_setup_entry.mock_calls) == 1
@pytest.mark.parametrize(
("side_effect", "error_key"),
[
(GatusClientError("Cannot connect"), "cannot_connect"),
(Exception("Unexpected backend explosion"), "unknown"),
],
)
async def test_form_failures_and_recovery(
hass: HomeAssistant,
mock_setup_entry: AsyncMock,
mock_gatus_client: AsyncMock,
side_effect: Exception,
error_key: str,
) -> None:
"""Test handling validation failures and ensuring the flow can completely recover."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
mock_gatus_client.get_endpoints_statuses.side_effect = side_effect
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_URL: "http://gatus.example.com:8080"},
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": error_key}
mock_gatus_client.get_endpoints_statuses.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_URL: "http://gatus.example.com:8080"},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
assert len(mock_setup_entry.mock_calls) == 1
async def test_form_already_configured(
hass: HomeAssistant, mock_config_entry: MockConfigEntry
) -> None:
"""Test that duplicate configurations for the same base URL abort early."""
mock_config_entry.add_to_hass(hass)
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"],
{CONF_URL: "http://gatus.example.com:8080"},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
@pytest.mark.usefixtures("mock_gatus_client")
async def test_flow_reconfigure(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test reconfigure flow."""
mock_config_entry.add_to_hass(hass)
result = await mock_config_entry.start_reconfigure_flow(hass)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reconfigure"
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_URL: "http://gatus.example2.com:8080/"},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reconfigure_successful"
assert mock_config_entry.data == {
CONF_URL: "http://gatus.example2.com:8080",
}
@pytest.mark.parametrize(
("side_effect", "error_key"),
[
(GatusClientError("Cannot connect"), "cannot_connect"),
(Exception("Unexpected backend explosion"), "unknown"),
],
)
async def test_flow_reconfigure_errors(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_gatus_client: AsyncMock,
side_effect: Exception,
error_key: str,
) -> None:
"""Test reconfigure flow errors and recover."""
mock_config_entry.add_to_hass(hass)
result = await mock_config_entry.start_reconfigure_flow(hass)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reconfigure"
mock_gatus_client.get_endpoints_statuses.side_effect = side_effect
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_URL: "http://gatus.example2.com:8080"},
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": error_key}
mock_gatus_client.get_endpoints_statuses.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_URL: "http://gatus.example2.com:8080"},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reconfigure_successful"
assert mock_config_entry.data == {
CONF_URL: "http://gatus.example2.com:8080",
}
@pytest.mark.usefixtures("mock_gatus_client")
async def test_flow_reconfigure_already_configured(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test reconfigure flow aborts if the new URL is already configured."""
mock_config_entry.add_to_hass(hass)
other_entry = MockConfigEntry(
domain=DOMAIN,
data={CONF_URL: "http://gatus.example3.com:8080"},
entry_id="other_id",
)
other_entry.add_to_hass(hass)
result = await mock_config_entry.start_reconfigure_flow(hass)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reconfigure"
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_URL: "http://gatus.example3.com:8080"},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"