Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions homeassistant/components/reolink/siren.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class ReolinkHostSirenEntityDescription(
SIREN_ENTITIES = (
ReolinkSirenEntityDescription(
key="siren",
cmd_id=547,
translation_key="siren",
supported=lambda api, ch: api.supported(ch, "siren_play"),
),
Expand Down Expand Up @@ -100,6 +101,11 @@ def __init__(
self.entity_description = entity_description
super().__init__(reolink_data, channel)

@property
def is_on(self) -> bool | None:
"""State of the siren."""
return self._host.api.baichuan.siren_state(self._channel)

@raise_translated_error
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on the siren."""
Expand Down
38 changes: 11 additions & 27 deletions tests/components/devolo_home_control/conftest.py
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
209 changes: 95 additions & 114 deletions tests/components/devolo_home_control/test_config_flow.py
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -20,50 +19,63 @@

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)
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_user(hass: HomeAssistant) -> None:
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}
)
assert result["step_id"] == "user"
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}

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["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:
Expand All @@ -73,32 +85,45 @@ 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"
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{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"],
{"username": "test-username", "password": "test-password"},
{CONF_USERNAME: "test-username", CONF_PASSWORD: "correct-password"},
)

assert result["errors"] == {"base": "invalid_auth"}
assert result["type"] is FlowResultType.CREATE_ENTRY


async def test_zeroconf_wrong_device(hass: HomeAssistant) -> None:
Expand All @@ -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

Expand All @@ -128,116 +152,73 @@ 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)
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,
) 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


@pytest.mark.parametrize("credentials_valid", [False])
async def test_form_invalid_credentials_reauth(hass: HomeAssistant) -> None:
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"


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)
result = await mock_config.start_reauth_flow(hass)

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"}
Loading
Loading