diff --git a/homeassistant/components/flo/config_flow.py b/homeassistant/components/flo/config_flow.py index 1f8e5fc08bd..24208aa16a8 100644 --- a/homeassistant/components/flo/config_flow.py +++ b/homeassistant/components/flo/config_flow.py @@ -27,9 +27,8 @@ async def validate_input(hass: core.HomeAssistant, data): api = await async_get_api( data[CONF_USERNAME], data[CONF_PASSWORD], session=session ) - except RequestError: - raise CannotConnect - except Exception: # pylint: disable=broad-except + except RequestError as request_error: + _LOGGER.error("Error connecting to the Flo API: %s", request_error) raise CannotConnect user_info = await api.user.get_info() @@ -48,15 +47,13 @@ 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 CannotConnect: errors["base"] = "cannot_connect" - except Exception: # pylint: disable=broad-except - _LOGGER.exception("Unexpected exception") - errors["base"] = "unknown" return self.async_show_form( step_id="user", data_schema=DATA_SCHEMA, errors=errors diff --git a/homeassistant/components/flo/entity.py b/homeassistant/components/flo/entity.py index 10ffa835454..35c6e022dcf 100644 --- a/homeassistant/components/flo/entity.py +++ b/homeassistant/components/flo/entity.py @@ -60,10 +60,11 @@ class FloEntity(Entity): @property def should_poll(self) -> bool: """Poll state from device.""" - return True + return False async def async_update(self): """Update Flo entity.""" + await self._device.async_request_refresh() async def async_added_to_hass(self): """When entity is added to hass.""" diff --git a/homeassistant/components/flo/sensor.py b/homeassistant/components/flo/sensor.py index 2cbc43e8cd8..cac259f475f 100644 --- a/homeassistant/components/flo/sensor.py +++ b/homeassistant/components/flo/sensor.py @@ -35,7 +35,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): entities.extend([FloCurrentFlowRateSensor(device) for device in devices]) entities.extend([FloTemperatureSensor(device) for device in devices]) entities.extend([FloPressureSensor(device) for device in devices]) - async_add_entities(entities, True) + async_add_entities(entities) class FloDailyUsageSensor(FloEntity): diff --git a/tests/components/flo/conftest.py b/tests/components/flo/conftest.py index 5790d3d4eb3..69167b58a02 100644 --- a/tests/components/flo/conftest.py +++ b/tests/components/flo/conftest.py @@ -25,9 +25,7 @@ def config_entry(hass): @pytest.fixture def aioclient_mock_fixture(aioclient_mock): """Fixture to provide a aioclient mocker.""" - now = round(time.time()) - # Mocks the login response for flo. aioclient_mock.post( "https://api.meetflo.com/api/v1/users/auth", diff --git a/tests/components/flo/test_config_flow.py b/tests/components/flo/test_config_flow.py index bddea76e73c..265f2ae2d38 100644 --- a/tests/components/flo/test_config_flow.py +++ b/tests/components/flo/test_config_flow.py @@ -1,7 +1,12 @@ """Test the flo config flow.""" +import json +import time + from homeassistant import config_entries, setup from homeassistant.components.flo.const import DOMAIN +from .common import TEST_EMAIL_ADDRESS, TEST_PASSWORD, TEST_TOKEN, TEST_USER_ID + from tests.async_mock import patch @@ -20,20 +25,37 @@ async def test_form(hass, aioclient_mock_fixture): "homeassistant.components.flo.async_setup_entry", return_value=True ) as mock_setup_entry: result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - {"username": "test-username", "password": "test-password"}, + result["flow_id"], {"username": TEST_USER_ID, "password": TEST_PASSWORD} ) - assert result2["type"] == "create_entry" - assert result2["title"] == "Home" - assert result2["data"] == {"username": "test-username", "password": "test-password"} - await hass.async_block_till_done() - assert len(mock_setup.mock_calls) == 1 - assert len(mock_setup_entry.mock_calls) == 1 + assert result2["type"] == "create_entry" + assert result2["title"] == "Home" + assert result2["data"] == {"username": TEST_USER_ID, "password": TEST_PASSWORD} + await hass.async_block_till_done() + assert len(mock_setup.mock_calls) == 1 + assert len(mock_setup_entry.mock_calls) == 1 async def test_form_cannot_connect(hass, aioclient_mock): """Test we handle cannot connect error.""" + now = round(time.time()) + # Mocks a failed login response for flo. + aioclient_mock.post( + "https://api.meetflo.com/api/v1/users/auth", + json=json.dumps( + { + "token": TEST_TOKEN, + "tokenPayload": { + "user": {"user_id": TEST_USER_ID, "email": TEST_EMAIL_ADDRESS}, + "timestamp": now, + }, + "tokenExpiration": 86400, + "timeNow": now, + } + ), + headers={"Content-Type": "application/json"}, + status=400, + ) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) diff --git a/tests/components/flo/test_sensor.py b/tests/components/flo/test_sensor.py index 5db1fdacfe1..ab5132bd34e 100644 --- a/tests/components/flo/test_sensor.py +++ b/tests/components/flo/test_sensor.py @@ -1,6 +1,6 @@ """Test Flo by Moen sensor entities.""" from homeassistant.components.flo.const import DOMAIN as FLO_DOMAIN -from homeassistant.const import CONF_PASSWORD, CONF_USERNAME +from homeassistant.const import ATTR_ENTITY_ID, CONF_PASSWORD, CONF_USERNAME from homeassistant.setup import async_setup_component from .common import TEST_PASSWORD, TEST_USER_ID @@ -22,3 +22,27 @@ async def test_sensors(hass, config_entry, aioclient_mock_fixture): assert hass.states.get("sensor.water_flow_rate").state == "0" assert hass.states.get("sensor.water_pressure").state == "54.2" assert hass.states.get("sensor.water_temperature").state == "21.1" + + +async def test_manual_update_entity( + hass, config_entry, aioclient_mock_fixture, aioclient_mock +): + """Test manual update entity via service homeasasistant/update_entity.""" + config_entry.add_to_hass(hass) + assert await async_setup_component( + hass, FLO_DOMAIN, {CONF_USERNAME: TEST_USER_ID, CONF_PASSWORD: TEST_PASSWORD} + ) + await hass.async_block_till_done() + + assert len(hass.data[FLO_DOMAIN]["devices"]) == 1 + + await async_setup_component(hass, "homeassistant", {}) + + call_count = aioclient_mock.call_count + await hass.services.async_call( + "homeassistant", + "update_entity", + {ATTR_ENTITY_ID: ["sensor.current_system_mode"]}, + blocking=True, + ) + assert aioclient_mock.call_count == call_count + 2