diff --git a/homeassistant/components/risco/alarm_control_panel.py b/homeassistant/components/risco/alarm_control_panel.py index a92b3cc186a..096c4023ffe 100644 --- a/homeassistant/components/risco/alarm_control_panel.py +++ b/homeassistant/components/risco/alarm_control_panel.py @@ -4,19 +4,14 @@ import logging from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity from homeassistant.components.alarm_control_panel.const import ( SUPPORT_ALARM_ARM_AWAY, - SUPPORT_ALARM_ARM_CUSTOM_BYPASS, SUPPORT_ALARM_ARM_HOME, - SUPPORT_ALARM_ARM_NIGHT, ) from homeassistant.const import ( STATE_ALARM_ARMED_AWAY, - STATE_ALARM_ARMED_CUSTOM_BYPASS, STATE_ALARM_ARMED_HOME, - STATE_ALARM_ARMED_NIGHT, STATE_ALARM_ARMING, STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED, - STATE_UNKNOWN, ) from .const import DATA_COORDINATOR, DOMAIN @@ -27,8 +22,6 @@ SUPPORTED_STATES = [ STATE_ALARM_DISARMED, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, - STATE_ALARM_ARMED_NIGHT, - STATE_ALARM_ARMED_CUSTOM_BYPASS, STATE_ALARM_TRIGGERED, ] @@ -37,8 +30,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities): """Set up the Risco alarm control panel.""" coordinator = hass.data[DOMAIN][config_entry.entry_id][DATA_COORDINATOR] entities = [ - RiscoAlarm(hass, coordinator, partition_id) - for partition_id in coordinator.data.partitions.keys() + RiscoAlarm(coordinator, partition_id) + for partition_id in coordinator.data.partitions ] async_add_entities(entities, False) @@ -47,9 +40,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities): class RiscoAlarm(AlarmControlPanelEntity): """Representation of a Risco partition.""" - def __init__(self, hass, coordinator, partition_id): + def __init__(self, coordinator, partition_id): """Init the partition.""" - self._hass = hass self._coordinator = coordinator self._partition_id = partition_id self._partition = self._coordinator.data.partitions[self._partition_id] @@ -112,17 +104,12 @@ class RiscoAlarm(AlarmControlPanelEntity): if self._partition.disarmed: return STATE_ALARM_DISARMED - return STATE_UNKNOWN + return None @property def supported_features(self): """Return the list of supported features.""" - return ( - SUPPORT_ALARM_ARM_HOME - | SUPPORT_ALARM_ARM_AWAY - | SUPPORT_ALARM_ARM_NIGHT - | SUPPORT_ALARM_ARM_CUSTOM_BYPASS - ) + return SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY @property def code_arm_required(self): @@ -137,14 +124,6 @@ class RiscoAlarm(AlarmControlPanelEntity): """Send arm home command.""" await self._call_alarm_method("partial_arm") - async def async_alarm_arm_night(self, code=None): - """Send arm night command.""" - await self._call_alarm_method("partial_arm") - - async def async_alarm_arm_custom_bypass(self, code=None): - """Send arm custom bypass command.""" - await self._call_alarm_method("partial_arm") - async def async_alarm_arm_away(self, code=None): """Send arm away command.""" await self._call_alarm_method("arm") diff --git a/homeassistant/components/risco/config_flow.py b/homeassistant/components/risco/config_flow.py index 75807a63406..43fb75343cb 100644 --- a/homeassistant/components/risco/config_flow.py +++ b/homeassistant/components/risco/config_flow.py @@ -41,10 +41,11 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle the initial step.""" errors = {} if user_input is not None: + await self.async_set_unique_id(user_input[CONF_USERNAME]) + self._abort_if_unique_id_configured() + try: info = await validate_input(self.hass, user_input) - - return self.async_create_entry(title=info["title"], data=user_input) except CannotConnectError: errors["base"] = "cannot_connect" except UnauthorizedError: @@ -52,6 +53,8 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): except Exception: # pylint: disable=broad-except _LOGGER.exception("Unexpected exception") errors["base"] = "unknown" + else: + return self.async_create_entry(title=info["title"], data=user_input) return self.async_show_form( step_id="user", data_schema=DATA_SCHEMA, errors=errors diff --git a/tests/components/risco/test_alarm_control_panel.py b/tests/components/risco/test_alarm_control_panel.py index 574e422eda1..0219ceca7bd 100644 --- a/tests/components/risco/test_alarm_control_panel.py +++ b/tests/components/risco/test_alarm_control_panel.py @@ -9,9 +9,7 @@ from homeassistant.const import ( CONF_PIN, CONF_USERNAME, SERVICE_ALARM_ARM_AWAY, - SERVICE_ALARM_ARM_CUSTOM_BYPASS, SERVICE_ALARM_ARM_HOME, - SERVICE_ALARM_ARM_NIGHT, SERVICE_ALARM_DISARM, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, @@ -22,7 +20,7 @@ from homeassistant.const import ( ) from homeassistant.helpers.entity_component import async_update_entity -from tests.async_mock import AsyncMock, MagicMock, PropertyMock, patch +from tests.async_mock import MagicMock, PropertyMock, patch from tests.common import MockConfigEntry TEST_CONFIG = { @@ -60,14 +58,15 @@ def two_part_alarm(): "partitions", new_callable=PropertyMock(return_value=partition_mocks), ), patch( - "homeassistant.components.risco.RiscoAPI.get_state", - AsyncMock(return_value=alarm_mock), + "homeassistant.components.risco.RiscoAPI.get_state", return_value=alarm_mock, ): yield alarm_mock async def _setup_risco(hass, alarm=MagicMock()): config_entry = MockConfigEntry(domain=DOMAIN, data=TEST_CONFIG) + config_entry.add_to_hass(hass) + with patch( "homeassistant.components.risco.RiscoAPI.login", return_value=True, ), patch( @@ -77,9 +76,8 @@ async def _setup_risco(hass, alarm=MagicMock()): "homeassistant.components.risco.RiscoAPI.site_name", new_callable=PropertyMock(return_value=TEST_SITE_NAME), ), patch( - "homeassistant.components.risco.RiscoAPI.close", AsyncMock() + "homeassistant.components.risco.RiscoAPI.close" ): - config_entry.add_to_hass(hass) await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() @@ -194,9 +192,7 @@ async def test_states(hass, two_part_alarm): async def _test_servie_call(hass, service, method, entity_id, partition_id): - with patch( - "homeassistant.components.risco.RiscoAPI." + method, AsyncMock() - ) as set_mock: + with patch("homeassistant.components.risco.RiscoAPI." + method) as set_mock: await _call_alarm_service(hass, service, entity_id) set_mock.assert_awaited_once_with(partition_id) @@ -223,15 +219,3 @@ async def test_sets(hass, two_part_alarm): await _test_servie_call( hass, SERVICE_ALARM_ARM_HOME, "partial_arm", SECOND_ENTITY_ID, 1 ) - await _test_servie_call( - hass, SERVICE_ALARM_ARM_NIGHT, "partial_arm", FIRST_ENTITY_ID, 0 - ) - await _test_servie_call( - hass, SERVICE_ALARM_ARM_NIGHT, "partial_arm", SECOND_ENTITY_ID, 1 - ) - await _test_servie_call( - hass, SERVICE_ALARM_ARM_CUSTOM_BYPASS, "partial_arm", FIRST_ENTITY_ID, 0 - ) - await _test_servie_call( - hass, SERVICE_ALARM_ARM_CUSTOM_BYPASS, "partial_arm", SECOND_ENTITY_ID, 1 - ) diff --git a/tests/components/risco/test_config_flow.py b/tests/components/risco/test_config_flow.py index 8886930100a..259f5dfe15d 100644 --- a/tests/components/risco/test_config_flow.py +++ b/tests/components/risco/test_config_flow.py @@ -1,12 +1,13 @@ """Test the Risco config flow.""" -from homeassistant import config_entries, setup +from homeassistant import config_entries from homeassistant.components.risco.config_flow import ( CannotConnectError, UnauthorizedError, ) from homeassistant.components.risco.const import DOMAIN -from tests.async_mock import AsyncMock, PropertyMock, patch +from tests.async_mock import PropertyMock, patch +from tests.common import MockConfigEntry TEST_SITE_NAME = "test-site-name" TEST_DATA = { @@ -18,7 +19,6 @@ TEST_DATA = { async def test_form(hass): """Test we get the form.""" - await setup.async_setup_component(hass, "persistent_notification", {}) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) @@ -31,7 +31,7 @@ async def test_form(hass): "homeassistant.components.risco.config_flow.RiscoAPI.site_name", new_callable=PropertyMock(return_value=TEST_SITE_NAME), ), patch( - "homeassistant.components.risco.config_flow.RiscoAPI.close", AsyncMock() + "homeassistant.components.risco.config_flow.RiscoAPI.close" ) as mock_close, patch( "homeassistant.components.risco.async_setup", return_value=True ) as mock_setup, patch( @@ -59,9 +59,7 @@ async def test_form_invalid_auth(hass): with patch( "homeassistant.components.risco.config_flow.RiscoAPI.login", side_effect=UnauthorizedError, - ), patch( - "homeassistant.components.risco.config_flow.RiscoAPI.close", AsyncMock() - ) as mock_close: + ), patch("homeassistant.components.risco.config_flow.RiscoAPI.close") as mock_close: result2 = await hass.config_entries.flow.async_configure( result["flow_id"], TEST_DATA ) @@ -80,9 +78,7 @@ async def test_form_cannot_connect(hass): with patch( "homeassistant.components.risco.config_flow.RiscoAPI.login", side_effect=CannotConnectError, - ), patch( - "homeassistant.components.risco.config_flow.RiscoAPI.close", AsyncMock() - ) as mock_close: + ), patch("homeassistant.components.risco.config_flow.RiscoAPI.close") as mock_close: result2 = await hass.config_entries.flow.async_configure( result["flow_id"], TEST_DATA ) @@ -101,9 +97,7 @@ async def test_form_exception(hass): with patch( "homeassistant.components.risco.config_flow.RiscoAPI.login", side_effect=Exception, - ), patch( - "homeassistant.components.risco.config_flow.RiscoAPI.close", AsyncMock() - ) as mock_close: + ), patch("homeassistant.components.risco.config_flow.RiscoAPI.close") as mock_close: result2 = await hass.config_entries.flow.async_configure( result["flow_id"], TEST_DATA ) @@ -111,3 +105,24 @@ async def test_form_exception(hass): assert result2["type"] == "form" assert result2["errors"] == {"base": "unknown"} mock_close.assert_awaited_once() + + +async def test_form_already_exists(hass): + """Test that a flow with an existing username aborts.""" + entry = MockConfigEntry( + domain=DOMAIN, unique_id=TEST_DATA["username"], data=TEST_DATA, + ) + + entry.add_to_hass(hass) + await hass.async_block_till_done() + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], TEST_DATA + ) + + assert result2["type"] == "abort" + assert result2["reason"] == "already_configured"