diff --git a/tests/components/nut/test_config_flow.py b/tests/components/nut/test_config_flow.py index 0799248384b..68b5356a32c 100644 --- a/tests/components/nut/test_config_flow.py +++ b/tests/components/nut/test_config_flow.py @@ -2,19 +2,30 @@ from unittest.mock import patch -from homeassistant import config_entries, data_entry_flow +from pynut2.nut2 import PyNUTError + +from homeassistant import config_entries, data_entry_flow, setup from homeassistant.components.nut.const import DOMAIN -from homeassistant.const import CONF_RESOURCES, CONF_SCAN_INTERVAL +from homeassistant.const import ( + CONF_ALIAS, + CONF_HOST, + CONF_NAME, + CONF_PASSWORD, + CONF_PORT, + CONF_RESOURCES, + CONF_SCAN_INTERVAL, + CONF_USERNAME, +) from .util import _get_mock_pynutclient from tests.common import MockConfigEntry VALID_CONFIG = { - "host": "localhost", - "port": 123, - "name": "name", - "resources": ["battery.charge"], + CONF_HOST: "localhost", + CONF_PORT: 123, + CONF_NAME: "name", + CONF_RESOURCES: ["battery.charge"], } @@ -23,7 +34,7 @@ async def test_form_zeroconf(hass): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_ZEROCONF}, - data={"host": "192.168.1.5", "port": 1234}, + data={CONF_HOST: "192.168.1.5", CONF_PORT: 1234}, ) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["step_id"] == "user" @@ -39,11 +50,11 @@ async def test_form_zeroconf(hass): ): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], - {"username": "test-username", "password": "test-password"}, + {CONF_USERNAME: "test-username", CONF_PASSWORD: "test-password"}, ) assert result2["step_id"] == "resources" - assert result2["type"] == "form" + assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM with patch( "homeassistant.components.nut.PyNUTClient", @@ -54,18 +65,18 @@ async def test_form_zeroconf(hass): ) as mock_setup_entry: result3 = await hass.config_entries.flow.async_configure( result2["flow_id"], - {"resources": ["battery.voltage", "ups.status", "ups.status.display"]}, + {CONF_RESOURCES: ["battery.voltage", "ups.status", "ups.status.display"]}, ) await hass.async_block_till_done() - assert result3["type"] == "create_entry" + assert result3["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY assert result3["title"] == "192.168.1.5:1234" assert result3["data"] == { - "host": "192.168.1.5", - "password": "test-password", - "port": 1234, - "resources": ["battery.voltage", "ups.status", "ups.status.display"], - "username": "test-username", + CONF_HOST: "192.168.1.5", + CONF_PASSWORD: "test-password", + CONF_PORT: 1234, + CONF_RESOURCES: ["battery.voltage", "ups.status", "ups.status.display"], + CONF_USERNAME: "test-username", } assert result3["result"].unique_id is None assert len(mock_setup_entry.mock_calls) == 1 @@ -73,11 +84,11 @@ async def test_form_zeroconf(hass): async def test_form_user_one_ups(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} ) - assert result["type"] == "form" + assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["errors"] == {} mock_pynut = _get_mock_pynutclient( @@ -91,15 +102,15 @@ async def test_form_user_one_ups(hass): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], { - "host": "1.1.1.1", - "username": "test-username", - "password": "test-password", - "port": 2222, + CONF_HOST: "1.1.1.1", + CONF_USERNAME: "test-username", + CONF_PASSWORD: "test-password", + CONF_PORT: 2222, }, ) assert result2["step_id"] == "resources" - assert result2["type"] == "form" + assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM with patch( "homeassistant.components.nut.PyNUTClient", @@ -110,36 +121,36 @@ async def test_form_user_one_ups(hass): ) as mock_setup_entry: result3 = await hass.config_entries.flow.async_configure( result2["flow_id"], - {"resources": ["battery.voltage", "ups.status", "ups.status.display"]}, + {CONF_RESOURCES: ["battery.voltage", "ups.status", "ups.status.display"]}, ) await hass.async_block_till_done() - assert result3["type"] == "create_entry" + assert result3["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY assert result3["title"] == "1.1.1.1:2222" assert result3["data"] == { - "host": "1.1.1.1", - "password": "test-password", - "port": 2222, - "resources": ["battery.voltage", "ups.status", "ups.status.display"], - "username": "test-username", + CONF_HOST: "1.1.1.1", + CONF_PASSWORD: "test-password", + CONF_PORT: 2222, + CONF_RESOURCES: ["battery.voltage", "ups.status", "ups.status.display"], + CONF_USERNAME: "test-username", } assert len(mock_setup_entry.mock_calls) == 1 async def test_form_user_multiple_ups(hass): """Test we get the form.""" + await setup.async_setup_component(hass, "persistent_notification", {}) config_entry = MockConfigEntry( domain=DOMAIN, - data={"host": "2.2.2.2", "port": 123, "resources": ["battery.charge"]}, - options={CONF_RESOURCES: ["battery.charge"]}, + data={CONF_HOST: "2.2.2.2", CONF_PORT: 123, CONF_RESOURCES: ["battery.charge"]}, ) config_entry.add_to_hass(hass) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) - assert result["type"] == "form" + assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["errors"] == {} mock_pynut = _get_mock_pynutclient( @@ -154,15 +165,15 @@ async def test_form_user_multiple_ups(hass): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], { - "host": "1.1.1.1", - "username": "test-username", - "password": "test-password", - "port": 2222, + CONF_HOST: "1.1.1.1", + CONF_USERNAME: "test-username", + CONF_PASSWORD: "test-password", + CONF_PORT: 2222, }, ) assert result2["step_id"] == "ups" - assert result2["type"] == "form" + assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM with patch( "homeassistant.components.nut.PyNUTClient", @@ -170,11 +181,11 @@ async def test_form_user_multiple_ups(hass): ): result3 = await hass.config_entries.flow.async_configure( result2["flow_id"], - {"alias": "ups2"}, + {CONF_ALIAS: "ups2"}, ) assert result3["step_id"] == "resources" - assert result3["type"] == "form" + assert result3["type"] == data_entry_flow.RESULT_TYPE_FORM with patch( "homeassistant.components.nut.PyNUTClient", @@ -185,19 +196,19 @@ async def test_form_user_multiple_ups(hass): ) as mock_setup_entry: result4 = await hass.config_entries.flow.async_configure( result3["flow_id"], - {"resources": ["battery.voltage"]}, + {CONF_RESOURCES: ["battery.voltage"]}, ) await hass.async_block_till_done() - assert result4["type"] == "create_entry" + assert result4["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY assert result4["title"] == "ups2@1.1.1.1:2222" assert result4["data"] == { - "host": "1.1.1.1", - "password": "test-password", - "alias": "ups2", - "port": 2222, - "resources": ["battery.voltage"], - "username": "test-username", + CONF_HOST: "1.1.1.1", + CONF_PASSWORD: "test-password", + CONF_ALIAS: "ups2", + CONF_PORT: 2222, + CONF_RESOURCES: ["battery.voltage"], + CONF_USERNAME: "test-username", } assert len(mock_setup_entry.mock_calls) == 2 @@ -209,10 +220,11 @@ async def test_form_user_one_ups_with_ignored_entry(hass): ) ignored_entry.add_to_hass(hass) + await setup.async_setup_component(hass, "persistent_notification", {}) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) - assert result["type"] == "form" + assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["errors"] == {} mock_pynut = _get_mock_pynutclient( @@ -226,15 +238,15 @@ async def test_form_user_one_ups_with_ignored_entry(hass): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], { - "host": "1.1.1.1", - "username": "test-username", - "password": "test-password", - "port": 2222, + CONF_HOST: "1.1.1.1", + CONF_USERNAME: "test-username", + CONF_PASSWORD: "test-password", + CONF_PORT: 2222, }, ) assert result2["step_id"] == "resources" - assert result2["type"] == "form" + assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM with patch( "homeassistant.components.nut.PyNUTClient", @@ -245,18 +257,18 @@ async def test_form_user_one_ups_with_ignored_entry(hass): ) as mock_setup_entry: result3 = await hass.config_entries.flow.async_configure( result2["flow_id"], - {"resources": ["battery.voltage", "ups.status", "ups.status.display"]}, + {CONF_RESOURCES: ["battery.voltage", "ups.status", "ups.status.display"]}, ) await hass.async_block_till_done() - assert result3["type"] == "create_entry" + assert result3["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY assert result3["title"] == "1.1.1.1:2222" assert result3["data"] == { - "host": "1.1.1.1", - "password": "test-password", - "port": 2222, - "resources": ["battery.voltage", "ups.status", "ups.status.display"], - "username": "test-username", + CONF_HOST: "1.1.1.1", + CONF_PASSWORD: "test-password", + CONF_PORT: 2222, + CONF_RESOURCES: ["battery.voltage", "ups.status", "ups.status.display"], + CONF_USERNAME: "test-username", } assert len(mock_setup_entry.mock_calls) == 1 @@ -276,16 +288,143 @@ async def test_form_cannot_connect(hass): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], { - "host": "1.1.1.1", - "username": "test-username", - "password": "test-password", - "port": 2222, + CONF_HOST: "1.1.1.1", + CONF_USERNAME: "test-username", + CONF_PASSWORD: "test-password", + CONF_PORT: 2222, }, ) - assert result2["type"] == "form" + assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM assert result2["errors"] == {"base": "cannot_connect"} + with patch( + "homeassistant.components.nut.PyNUTClient.list_ups", + side_effect=PyNUTError, + ), patch( + "homeassistant.components.nut.PyNUTClient.list_vars", + side_effect=PyNUTError, + ): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_HOST: "1.1.1.1", + CONF_USERNAME: "test-username", + CONF_PASSWORD: "test-password", + CONF_PORT: 2222, + }, + ) + + assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM + assert result2["errors"] == {"base": "cannot_connect"} + + with patch( + "homeassistant.components.nut.PyNUTClient.list_ups", + return_value=["ups1"], + ), patch( + "homeassistant.components.nut.PyNUTClient.list_vars", + side_effect=TypeError, + ): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_HOST: "1.1.1.1", + CONF_USERNAME: "test-username", + CONF_PASSWORD: "test-password", + CONF_PORT: 2222, + }, + ) + + assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM + assert result2["errors"] == {"base": "unknown"} + + +async def test_abort_if_already_setup(hass): + """Test we abort if component is already setup.""" + config_entry = MockConfigEntry( + domain=DOMAIN, + data={ + CONF_HOST: "1.1.1.1", + CONF_PORT: 123, + CONF_RESOURCES: ["battery.voltage"], + }, + ) + config_entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + + mock_pynut = _get_mock_pynutclient( + list_vars={"battery.voltage": "voltage"}, + list_ups={"ups1": "UPS 1"}, + ) + + with patch( + "homeassistant.components.nut.PyNUTClient", + return_value=mock_pynut, + ): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_HOST: "1.1.1.1", + CONF_PORT: 123, + }, + ) + + assert result2["type"] == data_entry_flow.RESULT_TYPE_ABORT + assert result2["reason"] == "already_configured" + + +async def test_abort_if_already_setup_alias(hass): + """Test we abort if component is already setup with same alias.""" + config_entry = MockConfigEntry( + domain=DOMAIN, + data={ + CONF_HOST: "1.1.1.1", + CONF_PORT: 123, + CONF_RESOURCES: ["battery.voltage"], + CONF_ALIAS: "ups1", + }, + ) + config_entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + + mock_pynut = _get_mock_pynutclient( + list_vars={"battery.voltage": "voltage"}, + list_ups={"ups1": "UPS 1", "ups2": "UPS 2"}, + ) + + with patch( + "homeassistant.components.nut.PyNUTClient", + return_value=mock_pynut, + ): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_HOST: "1.1.1.1", + CONF_PORT: 123, + }, + ) + + assert result2["step_id"] == "ups" + assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM + + with patch( + "homeassistant.components.nut.PyNUTClient", + return_value=mock_pynut, + ): + result3 = await hass.config_entries.flow.async_configure( + result2["flow_id"], + {CONF_ALIAS: "ups1"}, + ) + + assert result3["type"] == data_entry_flow.RESULT_TYPE_ABORT + assert result3["reason"] == "already_configured" + async def test_options_flow(hass): """Test config flow options.""" diff --git a/tests/components/nut/test_sensor.py b/tests/components/nut/test_sensor.py index 4b1e1cc8a9a..5afc662251c 100644 --- a/tests/components/nut/test_sensor.py +++ b/tests/components/nut/test_sensor.py @@ -37,7 +37,7 @@ async def test_pr3000rt2u(hass): # Only test for a subset of attributes in case # HA changes the implementation and a new one appears assert all( - state.attributes[key] == expected_attributes[key] for key in expected_attributes + state.attributes[key] == attr for key, attr in expected_attributes.items() ) @@ -62,7 +62,7 @@ async def test_cp1350c(hass): # Only test for a subset of attributes in case # HA changes the implementation and a new one appears assert all( - state.attributes[key] == expected_attributes[key] for key in expected_attributes + state.attributes[key] == attr for key, attr in expected_attributes.items() ) @@ -86,7 +86,7 @@ async def test_5e850i(hass): # Only test for a subset of attributes in case # HA changes the implementation and a new one appears assert all( - state.attributes[key] == expected_attributes[key] for key in expected_attributes + state.attributes[key] == attr for key, attr in expected_attributes.items() ) @@ -110,7 +110,7 @@ async def test_5e650i(hass): # Only test for a subset of attributes in case # HA changes the implementation and a new one appears assert all( - state.attributes[key] == expected_attributes[key] for key in expected_attributes + state.attributes[key] == attr for key, attr in expected_attributes.items() ) @@ -137,7 +137,7 @@ async def test_backupsses600m1(hass): # Only test for a subset of attributes in case # HA changes the implementation and a new one appears assert all( - state.attributes[key] == expected_attributes[key] for key in expected_attributes + state.attributes[key] == attr for key, attr in expected_attributes.items() ) @@ -163,7 +163,7 @@ async def test_cp1500pfclcd(hass): # Only test for a subset of attributes in case # HA changes the implementation and a new one appears assert all( - state.attributes[key] == expected_attributes[key] for key in expected_attributes + state.attributes[key] == attr for key, attr in expected_attributes.items() ) @@ -187,7 +187,7 @@ async def test_dl650elcd(hass): # Only test for a subset of attributes in case # HA changes the implementation and a new one appears assert all( - state.attributes[key] == expected_attributes[key] for key in expected_attributes + state.attributes[key] == attr for key, attr in expected_attributes.items() ) @@ -211,7 +211,7 @@ async def test_blazer_usb(hass): # Only test for a subset of attributes in case # HA changes the implementation and a new one appears assert all( - state.attributes[key] == expected_attributes[key] for key in expected_attributes + state.attributes[key] == attr for key, attr in expected_attributes.items() )