Refactor tests for Shelly config flow (#143517)

* Add mock_setup_entry

* Add mock_setup

* Improve test_form_gen1_custom_port

* Improve test_form_errors_get_info

* Improve test_form_errors_test_connection

* Improve test_reconfigure_with_exception

* Improve test_form_auth_errors_test_connection_gen1

* Improve test_form_auth_errors_test_connection_gen2

* Cleaning

* Upate quality scale

* Always use result variable

* Remove unnecessary async_block_till_done
This commit is contained in:
Maciej Bieniek 2025-04-26 12:00:45 +02:00 committed by GitHub
parent f5d3495c62
commit f1b3b0c155
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 326 additions and 197 deletions

View File

@ -6,9 +6,7 @@ rules:
appropriate-polling: done
brands: done
common-modules: done
config-flow-test-coverage:
status: todo
comment: make sure flows end with created entry or abort
config-flow-test-coverage: done
config-flow: done
dependency-transparency: done
docs-actions:

View File

@ -1,5 +1,6 @@
"""Test configuration for Shelly."""
from collections.abc import Generator
from copy import deepcopy
from unittest.mock import AsyncMock, Mock, PropertyMock, patch
@ -690,3 +691,21 @@ async def mock_sleepy_rpc_device():
rpc_device_mock.return_value.mock_initialized = Mock(side_effect=initialized)
yield rpc_device_mock.return_value
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.shelly.async_setup_entry", return_value=True
) as mock_setup_entry:
yield mock_setup_entry
@pytest.fixture
def mock_setup() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.shelly.async_setup", return_value=True
) as mock_setup:
yield mock_setup

View File

@ -82,6 +82,8 @@ async def test_form(
port: int,
mock_block_device: Mock,
mock_rpc_device: Mock,
mock_setup_entry: AsyncMock,
mock_setup: AsyncMock,
) -> None:
"""Test we get the form."""
result = await hass.config_entries.flow.async_init(
@ -101,23 +103,15 @@ async def test_form(
"port": port,
},
),
patch(
"homeassistant.components.shelly.async_setup", return_value=True
) as mock_setup,
patch(
"homeassistant.components.shelly.async_setup_entry",
return_value=True,
) as mock_setup_entry,
):
result2 = await hass.config_entries.flow.async_configure(
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1", CONF_PORT: port},
)
await hass.async_block_till_done()
assert result2["type"] is FlowResultType.CREATE_ENTRY
assert result2["title"] == "Test name"
assert result2["data"] == {
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Test name"
assert result["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: port,
CONF_MODEL: model,
@ -131,26 +125,19 @@ async def test_form(
async def test_user_flow_overrides_existing_discovery(
hass: HomeAssistant,
mock_rpc_device: Mock,
mock_setup_entry: AsyncMock,
mock_setup: AsyncMock,
) -> None:
"""Test setting up from the user flow when the devices is already discovered."""
with (
patch(
"homeassistant.components.shelly.config_flow.get_info",
return_value={
"mac": "AABBCCDDEEFF",
"model": MODEL_PLUS_2PM,
"auth": False,
"gen": 2,
"port": 80,
},
),
patch(
"homeassistant.components.shelly.async_setup", return_value=True
) as mock_setup,
patch(
"homeassistant.components.shelly.async_setup_entry",
return_value=True,
) as mock_setup_entry,
with patch(
"homeassistant.components.shelly.config_flow.get_info",
return_value={
"mac": "AABBCCDDEEFF",
"model": MODEL_PLUS_2PM,
"auth": False,
"gen": 2,
"port": 80,
},
):
discovery_result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -172,22 +159,21 @@ async def test_user_flow_overrides_existing_discovery(
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}
result2 = await hass.config_entries.flow.async_configure(
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1", CONF_PORT: 80},
)
await hass.async_block_till_done()
assert result2["type"] is FlowResultType.CREATE_ENTRY
assert result2["title"] == "Test name"
assert result2["data"] == {
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Test name"
assert result["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: 80,
CONF_MODEL: MODEL_PLUS_2PM,
CONF_SLEEP_PERIOD: 0,
CONF_GEN: 2,
}
assert result2["context"]["unique_id"] == "AABBCCDDEEFF"
assert result["context"]["unique_id"] == "AABBCCDDEEFF"
assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
@ -198,6 +184,8 @@ async def test_user_flow_overrides_existing_discovery(
async def test_form_gen1_custom_port(
hass: HomeAssistant,
mock_block_device: Mock,
mock_setup_entry: AsyncMock,
mock_setup: AsyncMock,
) -> None:
"""Test we get the form."""
result = await hass.config_entries.flow.async_init(
@ -216,13 +204,35 @@ async def test_form_gen1_custom_port(
side_effect=CustomPortNotSupported,
),
):
result2 = await hass.config_entries.flow.async_configure(
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"host": "1.1.1.1", "port": "1100"},
{CONF_HOST: "1.1.1.1", CONF_PORT: "1100"},
)
assert result2["type"] is FlowResultType.FORM
assert result2["errors"]["base"] == "custom_port_not_supported"
assert result["type"] is FlowResultType.FORM
assert result["errors"]["base"] == "custom_port_not_supported"
with patch(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "type": MODEL_1, "gen": 1},
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1", CONF_PORT: DEFAULT_HTTP_PORT},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Test name"
assert result["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: DEFAULT_HTTP_PORT,
CONF_MODEL: MODEL_1,
CONF_SLEEP_PERIOD: 0,
CONF_GEN: 1,
}
assert result["context"]["unique_id"] == "test-mac"
assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1
@pytest.mark.parametrize(
@ -256,6 +266,8 @@ async def test_form_auth(
username: str,
mock_block_device: Mock,
mock_rpc_device: Mock,
mock_setup_entry: AsyncMock,
mock_setup: AsyncMock,
) -> None:
"""Test manual configuration if auth is required."""
result = await hass.config_entries.flow.async_init(
@ -268,31 +280,21 @@ async def test_form_auth(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "type": MODEL_1, "auth": True, "gen": gen},
):
result2 = await hass.config_entries.flow.async_configure(
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1"},
)
assert result2["type"] is FlowResultType.FORM
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}
with (
patch(
"homeassistant.components.shelly.async_setup", return_value=True
) as mock_setup,
patch(
"homeassistant.components.shelly.async_setup_entry",
return_value=True,
) as mock_setup_entry,
):
result3 = await hass.config_entries.flow.async_configure(
result2["flow_id"], user_input
)
await hass.async_block_till_done()
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input
)
assert result3["type"] is FlowResultType.CREATE_ENTRY
assert result3["title"] == "Test name"
assert result3["data"] == {
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Test name"
assert result["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: DEFAULT_HTTP_PORT,
CONF_MODEL: model,
@ -314,7 +316,12 @@ async def test_form_auth(
],
)
async def test_form_errors_get_info(
hass: HomeAssistant, exc: Exception, base_error: str
hass: HomeAssistant,
mock_block_device: Mock,
mock_setup: AsyncMock,
mock_setup_entry: AsyncMock,
exc: Exception,
base_error: str,
) -> None:
"""Test we handle errors."""
result = await hass.config_entries.flow.async_init(
@ -322,13 +329,35 @@ async def test_form_errors_get_info(
)
with patch("homeassistant.components.shelly.config_flow.get_info", side_effect=exc):
result2 = await hass.config_entries.flow.async_configure(
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1"},
)
assert result2["type"] is FlowResultType.FORM
assert result2["errors"] == {"base": base_error}
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": base_error}
with patch(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "type": MODEL_1, "gen": 1},
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1"},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Test name"
assert result["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: DEFAULT_HTTP_PORT,
CONF_MODEL: MODEL_1,
CONF_SLEEP_PERIOD: 0,
CONF_GEN: 1,
}
assert result["context"]["unique_id"] == "test-mac"
assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1
async def test_form_missing_model_key(
@ -343,13 +372,13 @@ async def test_form_missing_model_key(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "auth": False, "gen": "2"},
):
result2 = await hass.config_entries.flow.async_configure(
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1"},
)
assert result2["type"] is FlowResultType.ABORT
assert result2["reason"] == "firmware_not_fully_provisioned"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "firmware_not_fully_provisioned"
async def test_form_missing_model_key_auth_enabled(
@ -366,20 +395,20 @@ async def test_form_missing_model_key_auth_enabled(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "auth": True, "gen": 2},
):
result2 = await hass.config_entries.flow.async_configure(
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1"},
)
assert result2["type"] is FlowResultType.FORM
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}
monkeypatch.setattr(mock_rpc_device, "shelly", {"gen": 2})
result3 = await hass.config_entries.flow.async_configure(
result2["flow_id"], {CONF_PASSWORD: "1234"}
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {CONF_PASSWORD: "1234"}
)
assert result3["type"] is FlowResultType.ABORT
assert result3["reason"] == "firmware_not_fully_provisioned"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "firmware_not_fully_provisioned"
async def test_form_missing_model_key_zeroconf(
@ -398,6 +427,7 @@ async def test_form_missing_model_key_zeroconf(
data=DISCOVERY_INFO,
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "firmware_not_fully_provisioned"
@ -411,7 +441,12 @@ async def test_form_missing_model_key_zeroconf(
],
)
async def test_form_errors_test_connection(
hass: HomeAssistant, exc: Exception, base_error: str
hass: HomeAssistant,
mock_block_device: Mock,
mock_setup_entry: AsyncMock,
mock_setup: AsyncMock,
exc: Exception,
base_error: str,
) -> None:
"""Test we handle errors."""
result = await hass.config_entries.flow.async_init(
@ -427,13 +462,35 @@ async def test_form_errors_test_connection(
"aioshelly.block_device.BlockDevice.create", new=AsyncMock(side_effect=exc)
),
):
result2 = await hass.config_entries.flow.async_configure(
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1"},
)
assert result2["type"] is FlowResultType.FORM
assert result2["errors"] == {"base": base_error}
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": base_error}
with patch(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "auth": False},
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1"},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Test name"
assert result["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: DEFAULT_HTTP_PORT,
CONF_MODEL: MODEL_1,
CONF_SLEEP_PERIOD: 0,
CONF_GEN: 1,
}
assert result["context"]["unique_id"] == "test-mac"
assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1
async def test_form_already_configured(hass: HomeAssistant) -> None:
@ -452,20 +509,23 @@ async def test_form_already_configured(hass: HomeAssistant) -> None:
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "type": MODEL_1, "auth": False},
):
result2 = await hass.config_entries.flow.async_configure(
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1"},
)
assert result2["type"] is FlowResultType.ABORT
assert result2["reason"] == "already_configured"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
# Test config entry got updated with latest IP
assert entry.data[CONF_HOST] == "1.1.1.1"
async def test_user_setup_ignored_device(
hass: HomeAssistant, mock_block_device: Mock
hass: HomeAssistant,
mock_block_device: Mock,
mock_setup_entry: AsyncMock,
mock_setup: AsyncMock,
) -> None:
"""Test user can successfully setup an ignored device."""
@ -481,25 +541,16 @@ async def test_user_setup_ignored_device(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with (
patch(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "type": MODEL_1, "auth": False},
),
patch(
"homeassistant.components.shelly.async_setup", return_value=True
) as mock_setup,
patch(
"homeassistant.components.shelly.async_setup_entry",
return_value=True,
) as mock_setup_entry,
with patch(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "type": MODEL_1, "auth": False},
):
result2 = await hass.config_entries.flow.async_configure(
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1"},
)
assert result2["type"] is FlowResultType.CREATE_ENTRY
assert result["type"] is FlowResultType.CREATE_ENTRY
# Test config entry got updated with latest IP
assert entry.data[CONF_HOST] == "1.1.1.1"
@ -517,7 +568,12 @@ async def test_user_setup_ignored_device(
],
)
async def test_form_auth_errors_test_connection_gen1(
hass: HomeAssistant, exc: Exception, base_error: str
hass: HomeAssistant,
mock_block_device: Mock,
mock_setup: AsyncMock,
mock_setup_entry: AsyncMock,
exc: Exception,
base_error: str,
) -> None:
"""Test we handle errors in Gen1 authenticated devices."""
result = await hass.config_entries.flow.async_init(
@ -528,21 +584,45 @@ async def test_form_auth_errors_test_connection_gen1(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "auth": True},
):
result2 = await hass.config_entries.flow.async_configure(
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1"},
)
with patch(
"aioshelly.block_device.BlockDevice.create",
new=AsyncMock(side_effect=exc),
side_effect=exc,
):
result3 = await hass.config_entries.flow.async_configure(
result2["flow_id"],
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_USERNAME: "test username", CONF_PASSWORD: "test password"},
)
assert result3["type"] is FlowResultType.FORM
assert result3["errors"] == {"base": base_error}
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": base_error}
with patch(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "auth": True},
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_USERNAME: "test username", CONF_PASSWORD: "test password"},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Test name"
assert result["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: DEFAULT_HTTP_PORT,
CONF_MODEL: MODEL_1,
CONF_SLEEP_PERIOD: 0,
CONF_GEN: 1,
CONF_USERNAME: "test username",
CONF_PASSWORD: "test password",
}
assert result["context"]["unique_id"] == "test-mac"
assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1
@pytest.mark.parametrize(
@ -555,7 +635,12 @@ async def test_form_auth_errors_test_connection_gen1(
],
)
async def test_form_auth_errors_test_connection_gen2(
hass: HomeAssistant, exc: Exception, base_error: str
hass: HomeAssistant,
mock_rpc_device: Mock,
mock_setup: AsyncMock,
mock_setup_entry: AsyncMock,
exc: Exception,
base_error: str,
) -> None:
"""Test we handle errors in Gen2 authenticated devices."""
result = await hass.config_entries.flow.async_init(
@ -566,20 +651,44 @@ async def test_form_auth_errors_test_connection_gen2(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "auth": True, "gen": 2},
):
result2 = await hass.config_entries.flow.async_configure(
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_HOST: "1.1.1.1"},
)
with patch(
"aioshelly.rpc_device.RpcDevice.create",
new=AsyncMock(side_effect=exc),
side_effect=exc,
):
result3 = await hass.config_entries.flow.async_configure(
result2["flow_id"], {CONF_PASSWORD: "test password"}
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {CONF_PASSWORD: "test password"}
)
assert result3["type"] is FlowResultType.FORM
assert result3["errors"] == {"base": base_error}
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": base_error}
with patch(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "auth": True, "gen": 2},
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_PASSWORD: "test password"},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Test name"
assert result["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: DEFAULT_HTTP_PORT,
CONF_MODEL: "SNSW-002P16EU",
CONF_SLEEP_PERIOD: 0,
CONF_GEN: 2,
CONF_USERNAME: "admin",
CONF_PASSWORD: "test password",
}
assert result["context"]["unique_id"] == "test-mac"
assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1
@pytest.mark.parametrize(
@ -609,6 +718,8 @@ async def test_zeroconf(
get_info: dict[str, Any],
mock_block_device: Mock,
mock_rpc_device: Mock,
mock_setup_entry: AsyncMock,
mock_setup: AsyncMock,
) -> None:
"""Test we get the form."""
@ -629,24 +740,15 @@ async def test_zeroconf(
)
assert context["title_placeholders"]["name"] == "shelly1pm-12345"
assert context["confirm_only"] is True
with (
patch(
"homeassistant.components.shelly.async_setup", return_value=True
) as mock_setup,
patch(
"homeassistant.components.shelly.async_setup_entry",
return_value=True,
) as mock_setup_entry,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{},
)
await hass.async_block_till_done()
assert result2["type"] is FlowResultType.CREATE_ENTRY
assert result2["title"] == "Test name"
assert result2["data"] == {
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Test name"
assert result["data"] == {
CONF_HOST: "1.1.1.1",
CONF_MODEL: model,
CONF_SLEEP_PERIOD: 0,
@ -657,7 +759,11 @@ async def test_zeroconf(
async def test_zeroconf_sleeping_device(
hass: HomeAssistant, mock_block_device: Mock, monkeypatch: pytest.MonkeyPatch
hass: HomeAssistant,
mock_block_device: Mock,
monkeypatch: pytest.MonkeyPatch,
mock_setup_entry: AsyncMock,
mock_setup: AsyncMock,
) -> None:
"""Test sleeping device configuration via zeroconf."""
monkeypatch.setitem(
@ -687,24 +793,15 @@ async def test_zeroconf_sleeping_device(
if flow["flow_id"] == result["flow_id"]
)
assert context["title_placeholders"]["name"] == "shelly1pm-12345"
with (
patch(
"homeassistant.components.shelly.async_setup", return_value=True
) as mock_setup,
patch(
"homeassistant.components.shelly.async_setup_entry",
return_value=True,
) as mock_setup_entry,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{},
)
await hass.async_block_till_done()
assert result2["type"] is FlowResultType.CREATE_ENTRY
assert result2["title"] == "Test name"
assert result2["data"] == {
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Test name"
assert result["data"] == {
CONF_HOST: "1.1.1.1",
CONF_MODEL: MODEL_1,
CONF_SLEEP_PERIOD: 600,
@ -736,8 +833,9 @@ async def test_zeroconf_sleeping_device_error(hass: HomeAssistant) -> None:
data=DISCOVERY_INFO,
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "cannot_connect"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "cannot_connect"
async def test_options_flow_abort_setup_retry(
@ -789,8 +887,9 @@ async def test_zeroconf_already_configured(hass: HomeAssistant) -> None:
data=DISCOVERY_INFO,
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
# Test config entry got updated with latest IP
assert entry.data[CONF_HOST] == "1.1.1.1"
@ -816,8 +915,9 @@ async def test_zeroconf_ignored(hass: HomeAssistant) -> None:
data=DISCOVERY_INFO,
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
async def test_zeroconf_with_wifi_ap_ip(hass: HomeAssistant) -> None:
@ -839,8 +939,9 @@ async def test_zeroconf_with_wifi_ap_ip(hass: HomeAssistant) -> None:
),
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
# Test config entry was not updated with the wifi ap ip
assert entry.data[CONF_HOST] == "2.2.2.2"
@ -857,12 +958,16 @@ async def test_zeroconf_cannot_connect(hass: HomeAssistant) -> None:
data=DISCOVERY_INFO,
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "cannot_connect"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "cannot_connect"
async def test_zeroconf_require_auth(
hass: HomeAssistant, mock_block_device: Mock
hass: HomeAssistant,
mock_block_device: Mock,
mock_setup_entry: AsyncMock,
mock_setup: AsyncMock,
) -> None:
"""Test zeroconf if auth is required."""
@ -875,27 +980,18 @@ async def test_zeroconf_require_auth(
data=DISCOVERY_INFO,
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}
with (
patch(
"homeassistant.components.shelly.async_setup", return_value=True
) as mock_setup,
patch(
"homeassistant.components.shelly.async_setup_entry",
return_value=True,
) as mock_setup_entry,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_USERNAME: "test username", CONF_PASSWORD: "test password"},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}
assert result2["type"] is FlowResultType.CREATE_ENTRY
assert result2["title"] == "Test name"
assert result2["data"] == {
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_USERNAME: "test username", CONF_PASSWORD: "test password"},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Test name"
assert result["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: DEFAULT_HTTP_PORT,
CONF_MODEL: MODEL_1,
@ -944,8 +1040,8 @@ async def test_reauth_successful(
user_input=user_input,
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reauth_successful"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reauth_successful"
@pytest.mark.parametrize(
@ -1001,8 +1097,8 @@ async def test_reauth_unsuccessful(
user_input=user_input,
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == abort_reason
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == abort_reason
async def test_reauth_get_info_error(hass: HomeAssistant) -> None:
@ -1024,8 +1120,8 @@ async def test_reauth_get_info_error(hass: HomeAssistant) -> None:
user_input={CONF_PASSWORD: "test2 password"},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reauth_unsuccessful"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reauth_unsuccessful"
async def test_options_flow_disabled_gen_1(
@ -1105,7 +1201,6 @@ async def test_options_flow_ble(hass: HomeAssistant, mock_rpc_device: Mock) -> N
CONF_BLE_SCANNER_MODE: BLEScannerMode.DISABLED,
},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["data"][CONF_BLE_SCANNER_MODE] is BLEScannerMode.DISABLED
@ -1121,7 +1216,6 @@ async def test_options_flow_ble(hass: HomeAssistant, mock_rpc_device: Mock) -> N
CONF_BLE_SCANNER_MODE: BLEScannerMode.ACTIVE,
},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["data"][CONF_BLE_SCANNER_MODE] is BLEScannerMode.ACTIVE
@ -1137,7 +1231,6 @@ async def test_options_flow_ble(hass: HomeAssistant, mock_rpc_device: Mock) -> N
CONF_BLE_SCANNER_MODE: BLEScannerMode.PASSIVE,
},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["data"][CONF_BLE_SCANNER_MODE] is BLEScannerMode.PASSIVE
@ -1173,8 +1266,9 @@ async def test_zeroconf_already_configured_triggers_refresh_mac_in_name(
data=DISCOVERY_INFO_WITH_MAC,
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
monkeypatch.setattr(mock_rpc_device, "connected", False)
mock_rpc_device.mock_disconnected()
@ -1213,8 +1307,9 @@ async def test_zeroconf_already_configured_triggers_refresh(
data=DISCOVERY_INFO,
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
monkeypatch.setattr(mock_rpc_device, "connected", False)
mock_rpc_device.mock_disconnected()
@ -1263,8 +1358,9 @@ async def test_zeroconf_sleeping_device_not_triggers_refresh(
data=DISCOVERY_INFO,
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
monkeypatch.setattr(mock_rpc_device, "connected", False)
mock_rpc_device.mock_disconnected()
@ -1317,8 +1413,9 @@ async def test_zeroconf_sleeping_device_attempts_configure(
data=DISCOVERY_INFO,
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert mock_rpc_device.update_outbound_websocket.mock_calls == []
@ -1382,8 +1479,9 @@ async def test_zeroconf_sleeping_device_attempts_configure_ws_disabled(
data=DISCOVERY_INFO,
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert mock_rpc_device.update_outbound_websocket.mock_calls == []
@ -1447,8 +1545,9 @@ async def test_zeroconf_sleeping_device_attempts_configure_no_url_available(
data=DISCOVERY_INFO,
context={"source": config_entries.SOURCE_ZEROCONF},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert mock_rpc_device.update_outbound_websocket.mock_calls == []
@ -1493,8 +1592,8 @@ async def test_sleeping_device_gen2_with_new_firmware(
result["flow_id"],
{CONF_HOST: "1.1.1.1"},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["data"] == {
CONF_HOST: "1.1.1.1",
CONF_PORT: DEFAULT_HTTP_PORT,
@ -1608,6 +1707,19 @@ async def test_reconfigure_with_exception(
assert result["errors"] == {"base": base_error}
with patch(
"homeassistant.components.shelly.config_flow.get_info",
return_value={"mac": "test-mac", "type": MODEL_1, "auth": False, "gen": 2},
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={CONF_HOST: "10.10.10.10", CONF_PORT: 99},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reconfigure_successful"
assert entry.data == {CONF_HOST: "10.10.10.10", CONF_PORT: 99, CONF_GEN: 2}
async def test_zeroconf_rejects_ipv6(hass: HomeAssistant) -> None:
"""Test zeroconf discovery rejects ipv6."""