Refactor onewire options flow tests (#87711)

This commit is contained in:
epenet 2023-02-09 11:52:26 +01:00 committed by GitHub
parent 330e1c6cbb
commit 678d1e367d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 195 additions and 219 deletions

View File

@ -1,18 +1,27 @@
"""Tests for 1-Wire config flow.""" """Tests for 1-Wire config flow."""
from collections.abc import Generator
from unittest.mock import AsyncMock, patch from unittest.mock import AsyncMock, patch
from pyownet import protocol from pyownet import protocol
import pytest import pytest
from homeassistant.components.onewire.const import DOMAIN from homeassistant.components.onewire.const import (
DOMAIN,
INPUT_ENTRY_CLEAR_OPTIONS,
INPUT_ENTRY_DEVICE_SELECTION,
)
from homeassistant.config_entries import SOURCE_USER, ConfigEntry from homeassistant.config_entries import SOURCE_USER, ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PORT from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.config_validation import ensure_list
from .const import MOCK_OWPROXY_DEVICES
@pytest.fixture(autouse=True, name="mock_setup_entry") @pytest.fixture(autouse=True, name="mock_setup_entry")
def override_async_setup_entry() -> AsyncMock: def override_async_setup_entry() -> Generator[AsyncMock, None, None]:
"""Override async_setup_entry.""" """Override async_setup_entry."""
with patch( with patch(
"homeassistant.components.onewire.async_setup_entry", return_value=True "homeassistant.components.onewire.async_setup_entry", return_value=True
@ -20,7 +29,25 @@ def override_async_setup_entry() -> AsyncMock:
yield mock_setup_entry yield mock_setup_entry
async def test_user_flow(hass: HomeAssistant, mock_setup_entry: AsyncMock): @pytest.fixture
async def filled_device_registry(
hass: HomeAssistant, config_entry: ConfigEntry, device_registry: dr.DeviceRegistry
) -> dr.DeviceRegistry:
"""Fill device registry with mock devices."""
for device_details in MOCK_OWPROXY_DEVICES.values():
if infos := device_details.get("device_info"):
for info in ensure_list(infos):
device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
identifiers=info["identifiers"],
manufacturer=info["manufacturer"],
model=info["model"],
name=info["name"],
)
return device_registry
async def test_user_flow(hass: HomeAssistant, mock_setup_entry: AsyncMock) -> None:
"""Test user flow.""" """Test user flow."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER} DOMAIN, context={"source": SOURCE_USER}
@ -63,7 +90,7 @@ async def test_user_flow(hass: HomeAssistant, mock_setup_entry: AsyncMock):
async def test_user_duplicate( async def test_user_duplicate(
hass: HomeAssistant, config_entry: ConfigEntry, mock_setup_entry: AsyncMock hass: HomeAssistant, config_entry: ConfigEntry, mock_setup_entry: AsyncMock
): ) -> None:
"""Test user duplicate flow.""" """Test user duplicate flow."""
await hass.config_entries.async_setup(config_entry.entry_id) await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
@ -85,3 +112,167 @@ async def test_user_duplicate(
assert result["reason"] == "already_configured" assert result["reason"] == "already_configured"
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(mock_setup_entry.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1
@pytest.mark.usefixtures("filled_device_registry")
async def test_user_options_clear(
hass: HomeAssistant, config_entry: ConfigEntry
) -> None:
"""Test clearing the options."""
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
# Verify that first config step comes back with a selection list of all the 28-family devices
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["data_schema"].schema["device_selection"].options == {
"28.111111111111": False,
"28.222222222222": False,
"28.222222222223": False,
}
# Verify that the clear-input action clears the options dict
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={INPUT_ENTRY_CLEAR_OPTIONS: True},
)
assert result["type"] == FlowResultType.CREATE_ENTRY
assert result["data"] == {}
@pytest.mark.usefixtures("filled_device_registry")
async def test_user_options_empty_selection(
hass: HomeAssistant, config_entry: ConfigEntry
) -> None:
"""Test leaving the selection of devices empty."""
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
# Verify that first config step comes back with a selection list of all the 28-family devices
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["data_schema"].schema["device_selection"].options == {
"28.111111111111": False,
"28.222222222222": False,
"28.222222222223": False,
}
# Verify that an empty selection does not modify the options
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={INPUT_ENTRY_DEVICE_SELECTION: []},
)
assert result["type"] == FlowResultType.FORM
assert result["step_id"] == "device_selection"
assert result["errors"] == {"base": "device_not_selected"}
@pytest.mark.usefixtures("filled_device_registry")
async def test_user_options_set_single(
hass: HomeAssistant, config_entry: ConfigEntry
) -> None:
"""Test configuring a single device."""
# Clear config options to certify functionality when starting from scratch
config_entry.options = {}
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
# Verify that first config step comes back with a selection list of all the 28-family devices
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["data_schema"].schema["device_selection"].options == {
"28.111111111111": False,
"28.222222222222": False,
"28.222222222223": False,
}
# Verify that a single selected device to configure comes back as a form with the device to configure
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={INPUT_ENTRY_DEVICE_SELECTION: ["28.111111111111"]},
)
assert result["type"] == FlowResultType.FORM
assert result["description_placeholders"]["sensor_id"] == "28.111111111111"
# Verify that the setting for the device comes back as default when no input is given
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={},
)
assert result["type"] == FlowResultType.CREATE_ENTRY
assert (
result["data"]["device_options"]["28.111111111111"]["precision"]
== "temperature"
)
async def test_user_options_set_multiple(
hass: HomeAssistant,
config_entry: ConfigEntry,
filled_device_registry: dr.DeviceRegistry,
) -> None:
"""Test configuring multiple consecutive devices in a row."""
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
# Verify that first config step comes back with a selection list of all the 28-family devices
for entry in dr.async_entries_for_config_entry(
filled_device_registry, config_entry.entry_id
):
filled_device_registry.async_update_device(entry.id, name_by_user="Given Name")
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["data_schema"].schema["device_selection"].options == {
"Given Name (28.111111111111)": False,
"Given Name (28.222222222222)": False,
"Given Name (28.222222222223)": False,
}
# Verify that selecting two devices to configure comes back as a
# form with the first device to configure using it's long name as entry
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
INPUT_ENTRY_DEVICE_SELECTION: [
"Given Name (28.111111111111)",
"Given Name (28.222222222222)",
]
},
)
assert result["type"] == FlowResultType.FORM
assert (
result["description_placeholders"]["sensor_id"]
== "Given Name (28.222222222222)"
)
# Verify that next sensor is coming up for configuration after the first
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={"precision": "temperature"},
)
assert result["type"] == FlowResultType.FORM
assert (
result["description_placeholders"]["sensor_id"]
== "Given Name (28.111111111111)"
)
# Verify that the setting for the device comes back as default when no input is given
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={"precision": "temperature9"},
)
assert result["type"] == FlowResultType.CREATE_ENTRY
assert (
result["data"]["device_options"]["28.222222222222"]["precision"]
== "temperature"
)
assert (
result["data"]["device_options"]["28.111111111111"]["precision"]
== "temperature9"
)
async def test_user_options_no_devices(
hass: HomeAssistant, config_entry: ConfigEntry
) -> None:
"""Test that options does not change when no devices are available."""
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
# Verify that first config step comes back with an empty list of possible devices to choose from
result = await hass.config_entries.options.async_init(config_entry.entry_id)
await hass.async_block_till_done()
assert result["type"] == FlowResultType.ABORT
assert result["reason"] == "No configurable devices found."

View File

@ -1,215 +0,0 @@
"""Tests for 1-Wire config flow."""
from unittest.mock import MagicMock, patch
from homeassistant.components.onewire.const import (
INPUT_ENTRY_CLEAR_OPTIONS,
INPUT_ENTRY_DEVICE_SELECTION,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers import device_registry as dr
from . import setup_owproxy_mock_devices
from .const import MOCK_OWPROXY_DEVICES
class FakeDevice:
"""Mock Class for mocking DeviceEntry."""
name_by_user = "Given Name"
async def test_user_options_clear(
hass: HomeAssistant,
config_entry: ConfigEntry,
owproxy: MagicMock,
):
"""Test clearing the options."""
setup_owproxy_mock_devices(
owproxy, Platform.SENSOR, [x for x in MOCK_OWPROXY_DEVICES if "28." in x]
)
# Verify that first config step comes back with a selection list of all the 28-family devices
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["data_schema"].schema["device_selection"].options == {
"28.111111111111": False,
"28.222222222222": False,
"28.222222222223": False,
}
# Verify that the clear-input action clears the options dict
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={INPUT_ENTRY_CLEAR_OPTIONS: True},
)
assert result["type"] == FlowResultType.CREATE_ENTRY
assert result["data"] == {}
async def test_user_options_empty_selection(
hass: HomeAssistant,
config_entry: ConfigEntry,
owproxy: MagicMock,
):
"""Test leaving the selection of devices empty."""
setup_owproxy_mock_devices(
owproxy, Platform.SENSOR, [x for x in MOCK_OWPROXY_DEVICES if "28." in x]
)
# Verify that first config step comes back with a selection list of all the 28-family devices
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["data_schema"].schema["device_selection"].options == {
"28.111111111111": False,
"28.222222222222": False,
"28.222222222223": False,
}
# Verify that an empty selection does not modify the options
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={INPUT_ENTRY_DEVICE_SELECTION: []},
)
assert result["type"] == FlowResultType.FORM
assert result["step_id"] == "device_selection"
assert result["errors"] == {"base": "device_not_selected"}
async def test_user_options_set_single(
hass: HomeAssistant,
config_entry: ConfigEntry,
owproxy: MagicMock,
):
"""Test configuring a single device."""
setup_owproxy_mock_devices(
owproxy, Platform.SENSOR, [x for x in MOCK_OWPROXY_DEVICES if "28." in x]
)
# Clear config options to certify functionality when starting from scratch
config_entry.options = {}
# Verify that first config step comes back with a selection list of all the 28-family devices
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["data_schema"].schema["device_selection"].options == {
"28.111111111111": False,
"28.222222222222": False,
"28.222222222223": False,
}
# Verify that a single selected device to configure comes back as a form with the device to configure
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={INPUT_ENTRY_DEVICE_SELECTION: ["28.111111111111"]},
)
assert result["type"] == FlowResultType.FORM
assert result["description_placeholders"]["sensor_id"] == "28.111111111111"
# Verify that the setting for the device comes back as default when no input is given
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={},
)
assert result["type"] == FlowResultType.CREATE_ENTRY
assert (
result["data"]["device_options"]["28.111111111111"]["precision"]
== "temperature"
)
async def test_user_options_set_multiple(
hass: HomeAssistant,
config_entry: ConfigEntry,
owproxy: MagicMock,
):
"""Test configuring multiple consecutive devices in a row."""
setup_owproxy_mock_devices(
owproxy, Platform.SENSOR, [x for x in MOCK_OWPROXY_DEVICES if "28." in x]
)
# Initialize onewire hub
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
# Verify that first config step comes back with a selection list of all the 28-family devices
device_registry = dr.async_get(hass)
for entry in dr.async_entries_for_config_entry(
device_registry, config_entry.entry_id
):
device_registry.async_update_device(entry.id, name_by_user="Given Name")
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["data_schema"].schema["device_selection"].options == {
"Given Name (28.111111111111)": False,
"Given Name (28.222222222222)": False,
"Given Name (28.222222222223)": False,
}
# Verify that selecting two devices to configure comes back as a
# form with the first device to configure using it's long name as entry
with patch(
"homeassistant.helpers.device_registry.DeviceRegistry.async_get_device",
return_value=FakeDevice(),
):
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
INPUT_ENTRY_DEVICE_SELECTION: [
"Given Name (28.111111111111)",
"Given Name (28.222222222222)",
]
},
)
assert result["type"] == FlowResultType.FORM
assert (
result["description_placeholders"]["sensor_id"]
== "Given Name (28.222222222222)"
)
# Verify that next sensor is coming up for configuration after the first
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={"precision": "temperature"},
)
assert result["type"] == FlowResultType.FORM
assert (
result["description_placeholders"]["sensor_id"]
== "Given Name (28.111111111111)"
)
# Verify that the setting for the device comes back as default when no input is given
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={"precision": "temperature9"},
)
assert result["type"] == FlowResultType.CREATE_ENTRY
assert (
result["data"]["device_options"]["28.222222222222"]["precision"]
== "temperature"
)
assert (
result["data"]["device_options"]["28.111111111111"]["precision"]
== "temperature9"
)
async def test_user_options_no_devices(
hass: HomeAssistant,
config_entry: ConfigEntry,
owproxy: MagicMock,
):
"""Test that options does not change when no devices are available."""
# Initialize onewire hub
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
# Verify that first config step comes back with an empty list of possible devices to choose from
result = await hass.config_entries.options.async_init(config_entry.entry_id)
await hass.async_block_till_done()
assert result["type"] == FlowResultType.ABORT
assert result["reason"] == "No configurable devices found."