core/tests/components/acmeda/test_config_flow.py

144 lines
4.0 KiB
Python
Raw Normal View History

Add Acmeda integration (#33384) * First cut of Rollease Acmeda Pulse Hub integration. * Acmeda integration improvements: - Moved common code into a base entity - Battery level sensor added - Localisation now working * Added requirement for aiopulse now that it has been uploaded to PyPI. * Exclude acmeda integration from coverage check as it relies on a hub being present. * Fix Travis CI build issues. * Remove unused constants. * Remove unused group logic from cover.py * Removed commented code from base.py * Remove sensors (battery entities) on removal of hub. * Remove unused groups from sensor.py * Acmeda device and entity update made fully asynchronous using subscriptions to remove need for config polling. * Updated aiopulse version dependency. Removed non-functional battery charging indication. * Rationalised common code to update entities into helpers.py * Fix linting issue. * Correct additional CI pylint errors. * Index config_entries by entry_id. Move entity loading and unloading to __init__.py Add entry_id to dispatcher signal Removed now unused polling code hub Added config_flow unit tests * Tweak to integration config_entry title. * Bumped aiopulse module to 0.3.2. Reduced verbosity of aiopulse module. * Changed to using direct write of device state. Removed old style async_step_init config_flow step. * Remove superfluous battery_level and device_state_attributes from battery entity. * Removal of unused strings. Removal of unused create_config_flow helper. Removal of stale comment. * Remove use of shared container to track existing enities. Moved removal and deregistration of entities to base class through use of dispatch helper. * Fixed strings.json * Fix incorrect use of remove instead of pop on dict. * Add support for tilting covers, bump aiopulse version number. * Bump aiopulse version to v0.3.4. Fixed bug in cover supported_features. * Bumped aiopulse version to 0.4.0 Update acmeda .coveragerc exclusions * Removed already configured hub check from __init__.py async_setup_entry Removed passing in hass reference to base entity class Renamed entity async_reset to async_will_remove_from_hass Changed device_info and properties Migrated to CoveEntity from CoverDevice Added dispatched_connect cleanup on hub removal Removed unused entries from manifest Removed override of battery icon Renamed translations folder * Reversed unintended change to .coveragerc * Fixed config flow for multi-hub discovery. * Acmeda enhancements as requested by MartinHjelmare * Force import to connect to hub to retrieve id prior to creating entry * Remove YAML configuration support. * Tidied up config_flow and tests: - removed unnecessary steps - fixed typos * Removed storage of hub in config_flow.
2020-05-17 10:15:06 +00:00
"""Define tests for the Acmeda config flow."""
import aiopulse
import pytest
from homeassistant import data_entry_flow
from homeassistant.components.acmeda.const import DOMAIN
from homeassistant.config_entries import SOURCE_USER
from homeassistant.const import CONF_HOST
from tests.async_mock import patch
Add Acmeda integration (#33384) * First cut of Rollease Acmeda Pulse Hub integration. * Acmeda integration improvements: - Moved common code into a base entity - Battery level sensor added - Localisation now working * Added requirement for aiopulse now that it has been uploaded to PyPI. * Exclude acmeda integration from coverage check as it relies on a hub being present. * Fix Travis CI build issues. * Remove unused constants. * Remove unused group logic from cover.py * Removed commented code from base.py * Remove sensors (battery entities) on removal of hub. * Remove unused groups from sensor.py * Acmeda device and entity update made fully asynchronous using subscriptions to remove need for config polling. * Updated aiopulse version dependency. Removed non-functional battery charging indication. * Rationalised common code to update entities into helpers.py * Fix linting issue. * Correct additional CI pylint errors. * Index config_entries by entry_id. Move entity loading and unloading to __init__.py Add entry_id to dispatcher signal Removed now unused polling code hub Added config_flow unit tests * Tweak to integration config_entry title. * Bumped aiopulse module to 0.3.2. Reduced verbosity of aiopulse module. * Changed to using direct write of device state. Removed old style async_step_init config_flow step. * Remove superfluous battery_level and device_state_attributes from battery entity. * Removal of unused strings. Removal of unused create_config_flow helper. Removal of stale comment. * Remove use of shared container to track existing enities. Moved removal and deregistration of entities to base class through use of dispatch helper. * Fixed strings.json * Fix incorrect use of remove instead of pop on dict. * Add support for tilting covers, bump aiopulse version number. * Bump aiopulse version to v0.3.4. Fixed bug in cover supported_features. * Bumped aiopulse version to 0.4.0 Update acmeda .coveragerc exclusions * Removed already configured hub check from __init__.py async_setup_entry Removed passing in hass reference to base entity class Renamed entity async_reset to async_will_remove_from_hass Changed device_info and properties Migrated to CoveEntity from CoverDevice Added dispatched_connect cleanup on hub removal Removed unused entries from manifest Removed override of battery icon Renamed translations folder * Reversed unintended change to .coveragerc * Fixed config flow for multi-hub discovery. * Acmeda enhancements as requested by MartinHjelmare * Force import to connect to hub to retrieve id prior to creating entry * Remove YAML configuration support. * Tidied up config_flow and tests: - removed unnecessary steps - fixed typos * Removed storage of hub in config_flow.
2020-05-17 10:15:06 +00:00
from tests.common import MockConfigEntry
DUMMY_HOST1 = "127.0.0.1"
DUMMY_HOST2 = "127.0.0.2"
CONFIG = {
CONF_HOST: DUMMY_HOST1,
}
@pytest.fixture
def mock_hub_discover():
"""Mock the hub discover method."""
with patch("aiopulse.Hub.discover") as mock_discover:
yield mock_discover
@pytest.fixture
def mock_hub_run():
"""Mock the hub run method."""
with patch("aiopulse.Hub.run") as mock_run:
yield mock_run
async def async_generator(items):
"""Async yields items provided in a list."""
for item in items:
yield item
async def test_show_form_no_hubs(hass, mock_hub_discover):
"""Test that flow aborts if no hubs are discovered."""
mock_hub_discover.return_value = async_generator([])
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "all_configured"
# Check we performed the discovery
assert len(mock_hub_discover.mock_calls) == 1
async def test_show_form_one_hub(hass, mock_hub_discover, mock_hub_run):
"""Test that a config is created when one hub discovered."""
dummy_hub_1 = aiopulse.Hub(DUMMY_HOST1)
dummy_hub_1.id = "ABC123"
mock_hub_discover.return_value = async_generator([dummy_hub_1])
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["title"] == dummy_hub_1.id
assert result["result"].data == {
"host": DUMMY_HOST1,
}
# Check we performed the discovery
assert len(mock_hub_discover.mock_calls) == 1
async def test_show_form_two_hubs(hass, mock_hub_discover):
"""Test that the form is served when more than one hub discovered."""
dummy_hub_1 = aiopulse.Hub(DUMMY_HOST1)
dummy_hub_1.id = "ABC123"
dummy_hub_2 = aiopulse.Hub(DUMMY_HOST1)
dummy_hub_2.id = "DEF456"
mock_hub_discover.return_value = async_generator([dummy_hub_1, dummy_hub_2])
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "user"
# Check we performed the discovery
assert len(mock_hub_discover.mock_calls) == 1
async def test_create_second_entry(hass, mock_hub_run, mock_hub_discover):
"""Test that a config is created when a second hub is discovered."""
dummy_hub_1 = aiopulse.Hub(DUMMY_HOST1)
dummy_hub_1.id = "ABC123"
dummy_hub_2 = aiopulse.Hub(DUMMY_HOST2)
dummy_hub_2.id = "DEF456"
mock_hub_discover.return_value = async_generator([dummy_hub_1, dummy_hub_2])
MockConfigEntry(domain=DOMAIN, unique_id=dummy_hub_1.id, data=CONFIG).add_to_hass(
hass
)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["title"] == dummy_hub_2.id
assert result["result"].data == {
"host": DUMMY_HOST2,
}
async def test_already_configured(hass, mock_hub_discover):
"""Test that flow aborts when all hubs are configured."""
dummy_hub_1 = aiopulse.Hub(DUMMY_HOST1)
dummy_hub_1.id = "ABC123"
mock_hub_discover.return_value = async_generator([dummy_hub_1])
MockConfigEntry(domain=DOMAIN, unique_id=dummy_hub_1.id, data=CONFIG).add_to_hass(
hass
)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] == "abort"
assert result["reason"] == "all_configured"