From 32db1d1eb20b83a8ee912f9522bc5273b0fb5b49 Mon Sep 17 00:00:00 2001 From: Graham Wetzler Date: Fri, 21 Aug 2020 12:20:42 -0500 Subject: [PATCH] Improve tests and config flow for Smart Meter Texas (#39089) Co-authored-by: Martin Hjelmare --- .../components/smart_meter_texas/__init__.py | 12 ++++----- .../smart_meter_texas/config_flow.py | 14 +++------- .../components/smart_meter_texas/conftest.py | 4 +-- .../components/smart_meter_texas/test_init.py | 27 +++++++++---------- .../smart_meter_texas/test_sensor.py | 6 +---- 5 files changed, 25 insertions(+), 38 deletions(-) diff --git a/homeassistant/components/smart_meter_texas/__init__.py b/homeassistant/components/smart_meter_texas/__init__.py index 29c961df5e0..e286bfb2557 100644 --- a/homeassistant/components/smart_meter_texas/__init__.py +++ b/homeassistant/components/smart_meter_texas/__init__.py @@ -45,21 +45,21 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): password = entry.data[CONF_PASSWORD] account = Account(username, password) - smartmetertexas = SmartMeterTexasData(hass, entry, account) + smart_meter_texas_data = SmartMeterTexasData(hass, entry, account) try: - await smartmetertexas.client.authenticate() + await smart_meter_texas_data.client.authenticate() except SmartMeterTexasAuthError: _LOGGER.error("Username or password was not accepted") return False except asyncio.TimeoutError: raise ConfigEntryNotReady - await smartmetertexas.setup() + await smart_meter_texas_data.setup() async def async_update_data(): _LOGGER.debug("Fetching latest data") - await smartmetertexas.read_meters() - return smartmetertexas + await smart_meter_texas_data.read_meters() + return smart_meter_texas_data # Use a DataUpdateCoordinator to manage the updates. This is due to the # Smart Meter Texas API which takes around 30 seconds to read a meter. @@ -78,7 +78,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): hass.data[DOMAIN][entry.entry_id] = { DATA_COORDINATOR: coordinator, - DATA_SMART_METER: smartmetertexas, + DATA_SMART_METER: smart_meter_texas_data, } asyncio.create_task(coordinator.async_refresh()) diff --git a/homeassistant/components/smart_meter_texas/config_flow.py b/homeassistant/components/smart_meter_texas/config_flow.py index 298831273e2..ce62be73c41 100644 --- a/homeassistant/components/smart_meter_texas/config_flow.py +++ b/homeassistant/components/smart_meter_texas/config_flow.py @@ -50,14 +50,6 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): VERSION = 1 CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL - def _account_already_configured(self, account): - existing_accounts = { - entry.data[CONF_USERNAME] - for entry in self._async_current_entries() - if CONF_USERNAME in entry.data - } - return account in existing_accounts - async def async_step_user(self, user_input=None): """Handle the initial step.""" @@ -74,8 +66,10 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): errors["base"] = "unknown" else: if not errors: - if self._account_already_configured(user_input[CONF_USERNAME]): - return self.async_abort(reason="already_configured") + # Ensure the same account cannot be setup more than once. + await self.async_set_unique_id(user_input[CONF_USERNAME]) + self._abort_if_unique_id_configured() + return self.async_create_entry(title=info["title"], data=user_input) return self.async_show_form( diff --git a/tests/components/smart_meter_texas/conftest.py b/tests/components/smart_meter_texas/conftest.py index 99df9380813..67e8472ae0b 100644 --- a/tests/components/smart_meter_texas/conftest.py +++ b/tests/components/smart_meter_texas/conftest.py @@ -32,9 +32,9 @@ def load_smt_fixture(name): return json.loads(json_fixture) -async def setup_integration(hass, config_entry, aioclient_mock): +async def setup_integration(hass, config_entry, aioclient_mock, **kwargs): """Initialize the Smart Meter Texas integration for testing.""" - mock_connection(aioclient_mock) + mock_connection(aioclient_mock, **kwargs) await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() diff --git a/tests/components/smart_meter_texas/test_init.py b/tests/components/smart_meter_texas/test_init.py index 5394c69a3f0..1ccb15714b1 100644 --- a/tests/components/smart_meter_texas/test_init.py +++ b/tests/components/smart_meter_texas/test_init.py @@ -1,18 +1,19 @@ """Test the Smart Meter Texas module.""" -import pytest - from homeassistant.components.homeassistant import ( DOMAIN as HA_DOMAIN, SERVICE_UPDATE_ENTITY, ) -from homeassistant.components.smart_meter_texas import async_setup_entry from homeassistant.components.smart_meter_texas.const import DOMAIN -from homeassistant.config_entries import ENTRY_STATE_LOADED, ENTRY_STATE_NOT_LOADED +from homeassistant.config_entries import ( + ENTRY_STATE_LOADED, + ENTRY_STATE_NOT_LOADED, + ENTRY_STATE_SETUP_ERROR, + ENTRY_STATE_SETUP_RETRY, +) from homeassistant.const import ATTR_ENTITY_ID -from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.setup import async_setup_component -from .conftest import TEST_ENTITY_ID, mock_connection, setup_integration +from .conftest import TEST_ENTITY_ID, setup_integration from tests.async_mock import patch @@ -28,25 +29,21 @@ async def test_setup_with_no_config(hass): async def test_auth_failure(hass, config_entry, aioclient_mock): """Test if user's username or password is not accepted.""" - mock_connection(aioclient_mock, auth_fail=True) - result = await async_setup_entry(hass, config_entry) + await setup_integration(hass, config_entry, aioclient_mock, auth_fail=True) - assert result is False + assert config_entry.state == ENTRY_STATE_SETUP_ERROR async def test_api_timeout(hass, config_entry, aioclient_mock): """Test that a timeout results in ConfigEntryNotReady.""" - mock_connection(aioclient_mock, auth_timeout=True) - with pytest.raises(ConfigEntryNotReady): - await async_setup_entry(hass, config_entry) + await setup_integration(hass, config_entry, aioclient_mock, auth_timeout=True) - assert config_entry.state == ENTRY_STATE_NOT_LOADED + assert config_entry.state == ENTRY_STATE_SETUP_RETRY async def test_update_failure(hass, config_entry, aioclient_mock): """Test that the coordinator handles a bad response.""" - mock_connection(aioclient_mock, bad_reading=True) - await setup_integration(hass, config_entry, aioclient_mock) + await setup_integration(hass, config_entry, aioclient_mock, bad_reading=True) await async_setup_component(hass, HA_DOMAIN, {}) with patch("smart_meter_texas.Meter.read_meter") as updater: await hass.services.async_call( diff --git a/tests/components/smart_meter_texas/test_sensor.py b/tests/components/smart_meter_texas/test_sensor.py index 54a3aeb80fa..104da011d90 100644 --- a/tests/components/smart_meter_texas/test_sensor.py +++ b/tests/components/smart_meter_texas/test_sensor.py @@ -11,14 +11,13 @@ from homeassistant.components.smart_meter_texas.const import ( from homeassistant.const import ATTR_ENTITY_ID, CONF_ADDRESS from homeassistant.setup import async_setup_component -from .conftest import TEST_ENTITY_ID, mock_connection, refresh_data, setup_integration +from .conftest import TEST_ENTITY_ID, refresh_data, setup_integration from tests.async_mock import patch async def test_sensor(hass, config_entry, aioclient_mock): """Test that the sensor is setup.""" - mock_connection(aioclient_mock) await setup_integration(hass, config_entry, aioclient_mock) await refresh_data(hass, config_entry, aioclient_mock) meter = hass.states.get(TEST_ENTITY_ID) @@ -29,7 +28,6 @@ async def test_sensor(hass, config_entry, aioclient_mock): async def test_name(hass, config_entry, aioclient_mock): """Test sensor name property.""" - mock_connection(aioclient_mock) await setup_integration(hass, config_entry, aioclient_mock) await refresh_data(hass, config_entry, aioclient_mock) meter = hass.states.get(TEST_ENTITY_ID) @@ -39,7 +37,6 @@ async def test_name(hass, config_entry, aioclient_mock): async def test_attributes(hass, config_entry, aioclient_mock): """Test meter attributes.""" - mock_connection(aioclient_mock) await setup_integration(hass, config_entry, aioclient_mock) await refresh_data(hass, config_entry, aioclient_mock) meter = hass.states.get(TEST_ENTITY_ID) @@ -51,7 +48,6 @@ async def test_attributes(hass, config_entry, aioclient_mock): async def test_generic_entity_update_service(hass, config_entry, aioclient_mock): """Test generic update entity service homeasasistant/update_entity.""" - mock_connection(aioclient_mock) await setup_integration(hass, config_entry, aioclient_mock) await async_setup_component(hass, HA_DOMAIN, {}) with patch("smart_meter_texas.Meter.read_meter") as updater: