diff --git a/homeassistant/components/prusalink/config_flow.py b/homeassistant/components/prusalink/config_flow.py index da21cca99de..6b0e6189f41 100644 --- a/homeassistant/components/prusalink/config_flow.py +++ b/homeassistant/components/prusalink/config_flow.py @@ -22,18 +22,9 @@ from .const import DOMAIN _LOGGER = logging.getLogger(__name__) -def add_protocol(value: str) -> str: - """Validate URL has a scheme.""" - value = value.rstrip("/") - if value.startswith(("http://", "https://")): - return value - - return f"http://{value}" - - STEP_USER_DATA_SCHEMA = vol.Schema( { - vol.Required("host"): vol.All(str, add_protocol), + vol.Required("host"): str, vol.Required("api_key"): str, } ) @@ -77,10 +68,18 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): step_id="user", data_schema=STEP_USER_DATA_SCHEMA ) + host = user_input["host"].rstrip("/") + if not host.startswith(("http://", "https://")): + host = f"http://{host}" + + data = { + "host": host, + "api_key": user_input["api_key"], + } errors = {} try: - info = await validate_input(self.hass, user_input) + info = await validate_input(self.hass, data) except CannotConnect: errors["base"] = "cannot_connect" except NotSupported: @@ -91,7 +90,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): _LOGGER.exception("Unexpected exception") errors["base"] = "unknown" else: - return self.async_create_entry(title=info["title"], data=user_input) + return self.async_create_entry(title=info["title"], data=data) return self.async_show_form( step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors diff --git a/tests/components/prusalink/test_camera.py b/tests/components/prusalink/test_camera.py index 36ec8ec3700..74354a75580 100644 --- a/tests/components/prusalink/test_camera.py +++ b/tests/components/prusalink/test_camera.py @@ -20,6 +20,7 @@ async def test_camera_no_job( hass: HomeAssistant, mock_config_entry, mock_api, + hass_client, ) -> None: """Test sensors while no job active.""" assert await async_setup_component(hass, "prusalink", {}) @@ -27,6 +28,10 @@ async def test_camera_no_job( assert state is not None assert state.state == "unavailable" + client = await hass_client() + resp = await client.get("/api/camera_proxy/camera.mock_title_job_preview") + assert resp.status == 500 + async def test_camera_active_job( hass: HomeAssistant, mock_config_entry, mock_api, mock_job_api_active, hass_client diff --git a/tests/components/prusalink/test_config_flow.py b/tests/components/prusalink/test_config_flow.py index 78cd652f5eb..4810ea82166 100644 --- a/tests/components/prusalink/test_config_flow.py +++ b/tests/components/prusalink/test_config_flow.py @@ -83,8 +83,8 @@ async def test_form_unknown(hass: HomeAssistant) -> None: assert result2["errors"] == {"base": "unknown"} -async def test_form_invalid_version(hass: HomeAssistant, mock_version_api) -> None: - """Test we handle invalid auth.""" +async def test_form_too_low_version(hass: HomeAssistant, mock_version_api) -> None: + """Test we handle too low API version.""" result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) @@ -103,6 +103,26 @@ async def test_form_invalid_version(hass: HomeAssistant, mock_version_api) -> No assert result2["errors"] == {"base": "not_supported"} +async def test_form_invalid_version_2(hass: HomeAssistant, mock_version_api) -> None: + """Test we handle invalid version.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + + mock_version_api["api"] = "i am not a version" + + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + "host": "1.1.1.1", + "api_key": "abcdefg", + }, + ) + + assert result2["type"] == FlowResultType.FORM + assert result2["errors"] == {"base": "not_supported"} + + async def test_form_cannot_connect(hass: HomeAssistant) -> None: """Test we handle cannot connect error.""" result = await hass.config_entries.flow.async_init( diff --git a/tests/components/prusalink/test_init.py b/tests/components/prusalink/test_init.py index a36c70bb882..2e15ac19193 100644 --- a/tests/components/prusalink/test_init.py +++ b/tests/components/prusalink/test_init.py @@ -1,16 +1,23 @@ """Test setting up and unloading PrusaLink.""" +from datetime import timedelta +from unittest.mock import patch +from pyprusalink import InvalidAuth, PrusaLinkError +import pytest from homeassistant.config_entries import ConfigEntry, ConfigEntryState from homeassistant.core import HomeAssistant +from homeassistant.util.dt import utcnow + +from tests.common import async_fire_time_changed -async def test_sensors_no_job( +async def test_unloading( hass: HomeAssistant, mock_config_entry: ConfigEntry, mock_api, ): - """Test sensors while no job active.""" + """Test unloading prusalink.""" assert await hass.config_entries.async_setup(mock_config_entry.entry_id) assert mock_config_entry.state == ConfigEntryState.LOADED @@ -21,3 +28,25 @@ async def test_sensors_no_job( for state in hass.states.async_all(): assert state.state == "unavailable" + + +@pytest.mark.parametrize("exception", [InvalidAuth, PrusaLinkError]) +async def test_failed_update( + hass: HomeAssistant, mock_config_entry: ConfigEntry, mock_api, exception +): + """Test failed update marks prusalink unavailable.""" + assert await hass.config_entries.async_setup(mock_config_entry.entry_id) + assert mock_config_entry.state == ConfigEntryState.LOADED + + with patch( + "homeassistant.components.prusalink.PrusaLink.get_printer", + side_effect=exception, + ), patch( + "homeassistant.components.prusalink.PrusaLink.get_job", + side_effect=exception, + ): + async_fire_time_changed(hass, utcnow() + timedelta(seconds=30), fire_all=True) + await hass.async_block_till_done() + + for state in hass.states.async_all(): + assert state.state == "unavailable"