Update Flo config flow and associated tests (#38722)

This commit is contained in:
David F. Mulcahey 2020-08-11 08:13:40 -04:00 committed by GitHub
parent 227d7c0a99
commit 6a24667944
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 62 additions and 20 deletions

View file

@ -27,9 +27,8 @@ async def validate_input(hass: core.HomeAssistant, data):
api = await async_get_api( api = await async_get_api(
data[CONF_USERNAME], data[CONF_PASSWORD], session=session data[CONF_USERNAME], data[CONF_PASSWORD], session=session
) )
except RequestError: except RequestError as request_error:
raise CannotConnect _LOGGER.error("Error connecting to the Flo API: %s", request_error)
except Exception: # pylint: disable=broad-except
raise CannotConnect raise CannotConnect
user_info = await api.user.get_info() user_info = await api.user.get_info()
@ -48,15 +47,13 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle the initial step.""" """Handle the initial step."""
errors = {} errors = {}
if user_input is not None: if user_input is not None:
await self.async_set_unique_id(user_input[CONF_USERNAME])
self._abort_if_unique_id_configured()
try: try:
info = await validate_input(self.hass, user_input) info = await validate_input(self.hass, user_input)
return self.async_create_entry(title=info["title"], data=user_input) return self.async_create_entry(title=info["title"], data=user_input)
except CannotConnect: except CannotConnect:
errors["base"] = "cannot_connect" errors["base"] = "cannot_connect"
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
return self.async_show_form( return self.async_show_form(
step_id="user", data_schema=DATA_SCHEMA, errors=errors step_id="user", data_schema=DATA_SCHEMA, errors=errors

View file

@ -60,10 +60,11 @@ class FloEntity(Entity):
@property @property
def should_poll(self) -> bool: def should_poll(self) -> bool:
"""Poll state from device.""" """Poll state from device."""
return True return False
async def async_update(self): async def async_update(self):
"""Update Flo entity.""" """Update Flo entity."""
await self._device.async_request_refresh()
async def async_added_to_hass(self): async def async_added_to_hass(self):
"""When entity is added to hass.""" """When entity is added to hass."""

View file

@ -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([FloCurrentFlowRateSensor(device) for device in devices])
entities.extend([FloTemperatureSensor(device) for device in devices]) entities.extend([FloTemperatureSensor(device) for device in devices])
entities.extend([FloPressureSensor(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): class FloDailyUsageSensor(FloEntity):

View file

@ -25,9 +25,7 @@ def config_entry(hass):
@pytest.fixture @pytest.fixture
def aioclient_mock_fixture(aioclient_mock): def aioclient_mock_fixture(aioclient_mock):
"""Fixture to provide a aioclient mocker.""" """Fixture to provide a aioclient mocker."""
now = round(time.time()) now = round(time.time())
# Mocks the login response for flo. # Mocks the login response for flo.
aioclient_mock.post( aioclient_mock.post(
"https://api.meetflo.com/api/v1/users/auth", "https://api.meetflo.com/api/v1/users/auth",

View file

@ -1,7 +1,12 @@
"""Test the flo config flow.""" """Test the flo config flow."""
import json
import time
from homeassistant import config_entries, setup from homeassistant import config_entries, setup
from homeassistant.components.flo.const import DOMAIN 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 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 "homeassistant.components.flo.async_setup_entry", return_value=True
) as mock_setup_entry: ) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"], {"username": TEST_USER_ID, "password": TEST_PASSWORD}
{"username": "test-username", "password": "test-password"},
) )
assert result2["type"] == "create_entry" assert result2["type"] == "create_entry"
assert result2["title"] == "Home" assert result2["title"] == "Home"
assert result2["data"] == {"username": "test-username", "password": "test-password"} assert result2["data"] == {"username": TEST_USER_ID, "password": TEST_PASSWORD}
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(mock_setup.mock_calls) == 1 assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1
async def test_form_cannot_connect(hass, aioclient_mock): async def test_form_cannot_connect(hass, aioclient_mock):
"""Test we handle cannot connect error.""" """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( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )

View file

@ -1,6 +1,6 @@
"""Test Flo by Moen sensor entities.""" """Test Flo by Moen sensor entities."""
from homeassistant.components.flo.const import DOMAIN as FLO_DOMAIN 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 homeassistant.setup import async_setup_component
from .common import TEST_PASSWORD, TEST_USER_ID 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_flow_rate").state == "0"
assert hass.states.get("sensor.water_pressure").state == "54.2" assert hass.states.get("sensor.water_pressure").state == "54.2"
assert hass.states.get("sensor.water_temperature").state == "21.1" 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