diff --git a/tests/components/devolo_home_control/conftest.py b/tests/components/devolo_home_control/conftest.py index 55e072d075c..33655c8cf83 100644 --- a/tests/components/devolo_home_control/conftest.py +++ b/tests/components/devolo_home_control/conftest.py @@ -1,41 +1,25 @@ """Fixtures for tests.""" from collections.abc import Generator +from itertools import cycle from unittest.mock import MagicMock, patch import pytest -@pytest.fixture -def credentials_valid() -> bool: - """Mark test as credentials invalid.""" - return True - - -@pytest.fixture -def maintenance() -> bool: - """Mark test as maintenance mode on.""" - return False - - @pytest.fixture(autouse=True) -def patch_mydevolo(credentials_valid: bool, maintenance: bool) -> Generator[None]: +def mydevolo() -> Generator[None]: """Fixture to patch mydevolo into a desired state.""" - with ( - patch( - "homeassistant.components.devolo_home_control.Mydevolo.credentials_valid", - return_value=credentials_valid, - ), - patch( - "homeassistant.components.devolo_home_control.Mydevolo.maintenance", - return_value=maintenance, - ), - patch( - "homeassistant.components.devolo_home_control.Mydevolo.get_gateway_ids", - return_value=["1400000000000001", "1400000000000002"], - ), + mydevolo = MagicMock() + mydevolo.uuid.return_value = "123456" + mydevolo.credentials_valid.return_value = True + mydevolo.maintenance.return_value = False + mydevolo.get_gateway_ids.return_value = ["1400000000000001", "1400000000000002"] + with patch( + "homeassistant.components.devolo_home_control.Mydevolo", + side_effect=cycle([mydevolo]), ): - yield + yield mydevolo @pytest.fixture(autouse=True) diff --git a/tests/components/devolo_home_control/test_config_flow.py b/tests/components/devolo_home_control/test_config_flow.py index 9367d746d2e..c872bc5c65b 100644 --- a/tests/components/devolo_home_control/test_config_flow.py +++ b/tests/components/devolo_home_control/test_config_flow.py @@ -1,13 +1,12 @@ """Test the devolo_home_control config flow.""" -from unittest.mock import patch - -import pytest +from unittest.mock import MagicMock from homeassistant import config_entries from homeassistant.components.devolo_home_control.const import DOMAIN +from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.core import HomeAssistant -from homeassistant.data_entry_flow import FlowResult, FlowResultType +from homeassistant.data_entry_flow import FlowResultType from .const import ( DISCOVERY_INFO, @@ -20,21 +19,6 @@ from tests.common import MockConfigEntry async def test_form(hass: HomeAssistant) -> None: """Test we get the form.""" - - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_USER} - ) - assert result["step_id"] == "user" - assert result["type"] is FlowResultType.FORM - assert result["errors"] == {} - - await _setup(hass, result) - - -@pytest.mark.parametrize("credentials_valid", [False]) -async def test_form_invalid_credentials_user(hass: HomeAssistant) -> None: - """Test if we get the error message on invalid credentials.""" - result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) @@ -44,26 +28,54 @@ async def test_form_invalid_credentials_user(hass: HomeAssistant) -> None: result = await hass.config_entries.flow.async_configure( result["flow_id"], - {"username": "test-username", "password": "test-password"}, + {CONF_USERNAME: "test-username", CONF_PASSWORD: "test-password"}, + ) + assert result["type"] is FlowResultType.CREATE_ENTRY + assert result["title"] == "devolo Home Control" + assert result["data"] == { + CONF_USERNAME: "test-username", + CONF_PASSWORD: "test-password", + } + + +async def test_form_invalid_credentials_user( + hass: HomeAssistant, mydevolo: MagicMock +) -> None: + """Test if we get the error message on invalid credentials.""" + mydevolo.credentials_valid.return_value = False + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} ) + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {CONF_USERNAME: "test-username", CONF_PASSWORD: "wrong-password"}, + ) + assert result["type"] is FlowResultType.FORM assert result["errors"] == {"base": "invalid_auth"} + mydevolo.credentials_valid.return_value = True + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {CONF_USERNAME: "test-username", CONF_PASSWORD: "correct-password"}, + ) + assert result["type"] is FlowResultType.CREATE_ENTRY + assert result["data"] == { + CONF_USERNAME: "test-username", + CONF_PASSWORD: "correct-password", + } + async def test_form_already_configured(hass: HomeAssistant) -> None: """Test if we get the error message on already configured.""" - with patch( - "homeassistant.components.devolo_home_control.Mydevolo.uuid", - return_value="123456", - ): - MockConfigEntry(domain=DOMAIN, unique_id="123456", data={}).add_to_hass(hass) - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": config_entries.SOURCE_USER}, - data={"username": "test-username", "password": "test-password"}, - ) - assert result["type"] is FlowResultType.ABORT - assert result["reason"] == "already_configured" + MockConfigEntry(domain=DOMAIN, unique_id="123456", data={}).add_to_hass(hass) + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_USER}, + data={CONF_USERNAME: "test-username", CONF_PASSWORD: "test-password"}, + ) + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "already_configured" async def test_form_zeroconf(hass: HomeAssistant) -> None: @@ -73,33 +85,46 @@ async def test_form_zeroconf(hass: HomeAssistant) -> None: context={"source": config_entries.SOURCE_ZEROCONF}, data=DISCOVERY_INFO, ) - assert result["step_id"] == "zeroconf_confirm" assert result["type"] is FlowResultType.FORM - await _setup(hass, result) + 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"] == "devolo Home Control" + assert result["data"] == { + CONF_USERNAME: "test-username", + CONF_PASSWORD: "test-password", + } -@pytest.mark.parametrize("credentials_valid", [False]) -async def test_form_invalid_credentials_zeroconf(hass: HomeAssistant) -> None: +async def test_form_invalid_credentials_zeroconf( + hass: HomeAssistant, mydevolo: MagicMock +) -> None: """Test if we get the error message on invalid credentials.""" - + mydevolo.credentials_valid.return_value = False result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_ZEROCONF}, data=DISCOVERY_INFO, ) - assert result["step_id"] == "zeroconf_confirm" - assert result["type"] is FlowResultType.FORM - result = await hass.config_entries.flow.async_configure( result["flow_id"], - {"username": "test-username", "password": "test-password"}, + {CONF_USERNAME: "test-username", CONF_PASSWORD: "test-password"}, ) - + assert result["type"] is FlowResultType.FORM assert result["errors"] == {"base": "invalid_auth"} + mydevolo.credentials_valid.return_value = True + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {CONF_USERNAME: "test-username", CONF_PASSWORD: "correct-password"}, + ) + assert result["type"] is FlowResultType.CREATE_ENTRY + async def test_zeroconf_wrong_device(hass: HomeAssistant) -> None: """Test that the zeroconf ignores wrong devices.""" @@ -108,7 +133,6 @@ async def test_zeroconf_wrong_device(hass: HomeAssistant) -> None: context={"source": config_entries.SOURCE_ZEROCONF}, data=DISCOVERY_INFO_WRONG_DEVOLO_DEVICE, ) - assert result["reason"] == "Not a devolo Home Control gateway." assert result["type"] is FlowResultType.ABORT @@ -128,8 +152,8 @@ async def test_form_reauth(hass: HomeAssistant) -> None: domain=DOMAIN, unique_id="123456", data={ - "username": "test-username", - "password": "test-password", + CONF_USERNAME: "test-username", + CONF_PASSWORD: "test-password", }, ) mock_config.add_to_hass(hass) @@ -137,35 +161,25 @@ async def test_form_reauth(hass: HomeAssistant) -> None: assert result["step_id"] == "reauth_confirm" assert result["type"] is FlowResultType.FORM - with ( - patch( - "homeassistant.components.devolo_home_control.async_setup_entry", - return_value=True, - ) as mock_setup_entry, - patch( - "homeassistant.components.devolo_home_control.Mydevolo.uuid", - return_value="123456", - ), - ): - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - {"username": "test-username-new", "password": "test-password-new"}, - ) - await hass.async_block_till_done() - - assert result2["type"] is FlowResultType.ABORT - assert len(mock_setup_entry.mock_calls) == 1 + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {CONF_USERNAME: "test-username-new", CONF_PASSWORD: "test-password-new"}, + ) + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "reauth_successful" -@pytest.mark.parametrize("credentials_valid", [False]) -async def test_form_invalid_credentials_reauth(hass: HomeAssistant) -> None: +async def test_form_invalid_credentials_reauth( + hass: HomeAssistant, mydevolo: MagicMock +) -> None: """Test if we get the error message on invalid credentials.""" + mydevolo.credentials_valid.return_value = False mock_config = MockConfigEntry( domain=DOMAIN, unique_id="123456", data={ - "username": "test-username", - "password": "test-password", + CONF_USERNAME: "test-username", + CONF_PASSWORD: "test-password", }, ) mock_config.add_to_hass(hass) @@ -173,71 +187,38 @@ async def test_form_invalid_credentials_reauth(hass: HomeAssistant) -> None: result = await hass.config_entries.flow.async_configure( result["flow_id"], - {"username": "test-username", "password": "test-password"}, + {CONF_USERNAME: "test-username", CONF_PASSWORD: "wrong-password"}, ) - assert result["errors"] == {"base": "invalid_auth"} + assert result["type"] is FlowResultType.FORM + + mydevolo.credentials_valid.return_value = True + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {CONF_USERNAME: "test-username-new", CONF_PASSWORD: "correct-password"}, + ) + assert result["reason"] == "reauth_successful" + assert result["type"] is FlowResultType.ABORT async def test_form_uuid_change_reauth(hass: HomeAssistant) -> None: """Test that the reauth confirmation form is served.""" mock_config = MockConfigEntry( domain=DOMAIN, - unique_id="123456", + unique_id="123457", data={ - "username": "test-username", - "password": "test-password", + CONF_USERNAME: "test-username", + CONF_PASSWORD: "test-password", }, ) mock_config.add_to_hass(hass) result = await mock_config.start_reauth_flow(hass) - assert result["step_id"] == "reauth_confirm" assert result["type"] is FlowResultType.FORM - with ( - patch( - "homeassistant.components.devolo_home_control.async_setup_entry", - return_value=True, - ), - patch( - "homeassistant.components.devolo_home_control.Mydevolo.uuid", - return_value="789123", - ), - ): - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - {"username": "test-username-new", "password": "test-password-new"}, - ) - await hass.async_block_till_done() - - assert result2["type"] is FlowResultType.FORM - assert result2["errors"] == {"base": "reauth_failed"} - - -async def _setup(hass: HomeAssistant, result: FlowResult) -> None: - """Finish configuration steps.""" - with ( - patch( - "homeassistant.components.devolo_home_control.async_setup_entry", - return_value=True, - ) as mock_setup_entry, - patch( - "homeassistant.components.devolo_home_control.Mydevolo.uuid", - return_value="123456", - ), - ): - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - {"username": "test-username", "password": "test-password"}, - ) - await hass.async_block_till_done() - - assert result2["type"] is FlowResultType.CREATE_ENTRY - assert result2["title"] == "devolo Home Control" - assert result2["data"] == { - "username": "test-username", - "password": "test-password", - } - - assert len(mock_setup_entry.mock_calls) == 1 + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {CONF_USERNAME: "test-username-new", CONF_PASSWORD: "test-password-new"}, + ) + assert result["type"] is FlowResultType.FORM + assert result["errors"] == {"base": "reauth_failed"} diff --git a/tests/components/devolo_home_control/test_init.py b/tests/components/devolo_home_control/test_init.py index fb97447264d..c9b39366cdd 100644 --- a/tests/components/devolo_home_control/test_init.py +++ b/tests/components/devolo_home_control/test_init.py @@ -1,9 +1,8 @@ """Tests for the devolo Home Control integration.""" -from unittest.mock import patch +from unittest.mock import MagicMock, patch from devolo_home_control_api.exceptions.gateway import GatewayOfflineError -import pytest from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN from homeassistant.components.devolo_home_control.const import DOMAIN @@ -27,17 +26,21 @@ async def test_setup_entry(hass: HomeAssistant) -> None: assert entry.state is ConfigEntryState.LOADED -@pytest.mark.parametrize("credentials_valid", [False]) -async def test_setup_entry_credentials_invalid(hass: HomeAssistant) -> None: +async def test_setup_entry_credentials_invalid( + hass: HomeAssistant, mydevolo: MagicMock +) -> None: """Test setup entry fails if credentials are invalid.""" + mydevolo.credentials_valid.return_value = False entry = configure_integration(hass) await hass.config_entries.async_setup(entry.entry_id) assert entry.state is ConfigEntryState.SETUP_ERROR -@pytest.mark.parametrize("maintenance", [True]) -async def test_setup_entry_maintenance(hass: HomeAssistant) -> None: +async def test_setup_entry_maintenance( + hass: HomeAssistant, mydevolo: MagicMock +) -> None: """Test setup entry fails if mydevolo is in maintenance mode.""" + mydevolo.maintenance.return_value = True entry = configure_integration(hass) await hass.config_entries.async_setup(entry.entry_id) assert entry.state is ConfigEntryState.SETUP_RETRY