Rework Comelit tests (#139475)

* Rework Comelit tests

* allign

* restore coverage
pull/125870/merge
Simone Chemelli 2025-02-28 20:45:47 +01:00 committed by GitHub
parent 1a80934593
commit 437e545116
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 304 additions and 168 deletions

View File

@ -1 +1,13 @@
"""Tests for the Comelit SimpleHome integration."""
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
async def setup_integration(hass: HomeAssistant, config_entry: MockConfigEntry) -> None:
"""Fixture for setting up the component."""
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()

View File

@ -0,0 +1,104 @@
"""Configure tests for Comelit SimpleHome."""
import pytest
from homeassistant.components.comelit.const import (
BRIDGE,
DOMAIN as COMELIT_DOMAIN,
VEDO,
)
from homeassistant.const import CONF_HOST, CONF_PIN, CONF_PORT, CONF_TYPE
from .const import (
BRIDGE_DEVICE_QUERY,
BRIDGE_HOST,
BRIDGE_PIN,
BRIDGE_PORT,
VEDO_DEVICE_QUERY,
VEDO_HOST,
VEDO_PIN,
VEDO_PORT,
)
from tests.common import AsyncMock, Generator, MockConfigEntry, patch
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.comelit.async_setup_entry",
return_value=True,
) as mock_setup_entry:
yield mock_setup_entry
@pytest.fixture
def mock_serial_bridge() -> Generator[AsyncMock]:
"""Mock a Comelit serial bridge."""
with (
patch(
"homeassistant.components.comelit.coordinator.ComeliteSerialBridgeApi",
autospec=True,
) as mock_comelit_serial_bridge,
patch(
"homeassistant.components.comelit.config_flow.ComeliteSerialBridgeApi",
new=mock_comelit_serial_bridge,
),
):
bridge = mock_comelit_serial_bridge.return_value
bridge.get_all_devices.return_value = BRIDGE_DEVICE_QUERY
bridge.host = BRIDGE_HOST
bridge.port = BRIDGE_PORT
bridge.pin = BRIDGE_PIN
yield bridge
@pytest.fixture
def mock_serial_bridge_config_entry() -> Generator[MockConfigEntry]:
"""Mock a Comelit config entry for Comelit bridge."""
return MockConfigEntry(
domain=COMELIT_DOMAIN,
data={
CONF_HOST: BRIDGE_HOST,
CONF_PORT: BRIDGE_PORT,
CONF_PIN: BRIDGE_PIN,
CONF_TYPE: BRIDGE,
},
)
@pytest.fixture
def mock_vedo() -> Generator[AsyncMock]:
"""Mock a Comelit vedo."""
with (
patch(
"homeassistant.components.comelit.coordinator.ComelitVedoApi",
autospec=True,
) as mock_comelit_vedo,
patch(
"homeassistant.components.comelit.config_flow.ComelitVedoApi",
new=mock_comelit_vedo,
),
):
vedo = mock_comelit_vedo.return_value
vedo.get_all_areas_and_zones.return_value = VEDO_DEVICE_QUERY
vedo.host = VEDO_HOST
vedo.port = VEDO_PORT
vedo.pin = VEDO_PIN
vedo.type = VEDO
yield vedo
@pytest.fixture
def mock_vedo_config_entry() -> Generator[MockConfigEntry]:
"""Mock a Comelit config entry for Comelit vedo."""
return MockConfigEntry(
domain=COMELIT_DOMAIN,
data={
CONF_HOST: VEDO_HOST,
CONF_PORT: VEDO_PORT,
CONF_PIN: VEDO_PIN,
CONF_TYPE: VEDO,
},
)

View File

@ -1,7 +1,10 @@
"""Common stuff for Comelit SimpleHome tests."""
from aiocomelit import ComelitVedoAreaObject, ComelitVedoZoneObject
from aiocomelit.api import ComelitSerialBridgeObject
from aiocomelit import (
ComelitSerialBridgeObject,
ComelitVedoAreaObject,
ComelitVedoZoneObject,
)
from aiocomelit.const import (
CLIMATE,
COVER,
@ -9,37 +12,20 @@ from aiocomelit.const import (
LIGHT,
OTHER,
SCENARIO,
VEDO,
WATT,
AlarmAreaState,
AlarmZoneState,
)
from homeassistant.components.comelit.const import DOMAIN
from homeassistant.const import CONF_DEVICES, CONF_HOST, CONF_PIN, CONF_PORT, CONF_TYPE
BRIDGE_HOST = "fake_bridge_host"
BRIDGE_PORT = 80
BRIDGE_PIN = 1234
MOCK_CONFIG = {
DOMAIN: {
CONF_DEVICES: [
{
CONF_HOST: "fake_host",
CONF_PORT: 80,
CONF_PIN: 1234,
},
{
CONF_HOST: "fake_vedo_host",
CONF_PORT: 8080,
CONF_PIN: 1234,
CONF_TYPE: VEDO,
},
]
}
}
VEDO_HOST = "fake_vedo_host"
VEDO_PORT = 8080
VEDO_PIN = 5678
MOCK_USER_BRIDGE_DATA = MOCK_CONFIG[DOMAIN][CONF_DEVICES][0]
MOCK_USER_VEDO_DATA = MOCK_CONFIG[DOMAIN][CONF_DEVICES][1]
FAKE_PIN = 5678
FAKE_PIN = 0000
BRIDGE_DEVICE_QUERY = {
CLIMATE: {},

View File

@ -57,9 +57,10 @@
}),
'entry': dict({
'data': dict({
'host': 'fake_host',
'host': 'fake_bridge_host',
'pin': '**REDACTED**',
'port': 80,
'type': 'Serial bridge',
}),
'disabled_by': None,
'discovery_keys': dict({

View File

@ -1,59 +1,93 @@
"""Tests for Comelit SimpleHome config flow."""
from typing import Any
from unittest.mock import patch
from unittest.mock import AsyncMock
from aiocomelit import CannotAuthenticate, CannotConnect
from aiocomelit.const import BRIDGE, VEDO
import pytest
from homeassistant.components.comelit.const import DOMAIN
from homeassistant.config_entries import SOURCE_USER
from homeassistant.const import CONF_HOST, CONF_PIN, CONF_PORT
from homeassistant.const import CONF_HOST, CONF_PIN, CONF_PORT, CONF_TYPE
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from .const import FAKE_PIN, MOCK_USER_BRIDGE_DATA, MOCK_USER_VEDO_DATA
from .const import (
BRIDGE_HOST,
BRIDGE_PIN,
BRIDGE_PORT,
FAKE_PIN,
VEDO_HOST,
VEDO_PIN,
VEDO_PORT,
)
from tests.common import MockConfigEntry
@pytest.mark.parametrize(
("class_api", "user_input"),
[
("ComeliteSerialBridgeApi", MOCK_USER_BRIDGE_DATA),
("ComelitVedoApi", MOCK_USER_VEDO_DATA),
],
)
async def test_full_flow(
hass: HomeAssistant, class_api: str, user_input: dict[str, Any]
async def test_flow_serial_bridge(
hass: HomeAssistant,
mock_serial_bridge: AsyncMock,
mock_serial_bridge_config_entry: MockConfigEntry,
) -> None:
"""Test starting a flow by user."""
with (
patch(
f"aiocomelit.api.{class_api}.login",
),
patch(
f"aiocomelit.api.{class_api}.logout",
),
patch("homeassistant.components.comelit.async_setup_entry") as mock_setup_entry,
):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input=user_input
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["data"][CONF_HOST] == user_input[CONF_HOST]
assert result["data"][CONF_PORT] == user_input[CONF_PORT]
assert result["data"][CONF_PIN] == user_input[CONF_PIN]
assert not result["result"].unique_id
await hass.async_block_till_done()
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert mock_setup_entry.called
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_HOST: BRIDGE_HOST,
CONF_PORT: BRIDGE_PORT,
CONF_PIN: BRIDGE_PIN,
},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["data"] == {
CONF_HOST: BRIDGE_HOST,
CONF_PORT: BRIDGE_PORT,
CONF_PIN: BRIDGE_PIN,
CONF_TYPE: BRIDGE,
}
assert not result["result"].unique_id
await hass.async_block_till_done()
async def test_flow_vedo(
hass: HomeAssistant,
mock_vedo: AsyncMock,
mock_vedo_config_entry: MockConfigEntry,
) -> None:
"""Test starting a flow by user."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_HOST: VEDO_HOST,
CONF_PORT: VEDO_PORT,
CONF_PIN: VEDO_PIN,
CONF_TYPE: VEDO,
},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["data"] == {
CONF_HOST: VEDO_HOST,
CONF_PORT: VEDO_PORT,
CONF_PIN: VEDO_PIN,
CONF_TYPE: VEDO,
}
assert not result["result"].unique_id
await hass.async_block_till_done()
@pytest.mark.parametrize(
@ -64,7 +98,13 @@ async def test_full_flow(
(ConnectionResetError, "unknown"),
],
)
async def test_exception_connection(hass: HomeAssistant, side_effect, error) -> None:
async def test_exception_connection(
hass: HomeAssistant,
mock_vedo: AsyncMock,
mock_vedo_config_entry: MockConfigEntry,
side_effect,
error,
) -> None:
"""Test starting a flow by user with a connection error."""
result = await hass.config_entries.flow.async_init(
@ -73,59 +113,65 @@ async def test_exception_connection(hass: HomeAssistant, side_effect, error) ->
assert result.get("type") is FlowResultType.FORM
assert result.get("step_id") == "user"
with (
patch(
"aiocomelit.api.ComeliteSerialBridgeApi.login",
side_effect=side_effect,
),
patch(
"aiocomelit.api.ComeliteSerialBridgeApi.logout",
),
patch(
"homeassistant.components.comelit.async_setup_entry",
),
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input=MOCK_USER_BRIDGE_DATA
)
mock_vedo.login.side_effect = side_effect
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert result["errors"] is not None
assert result["errors"]["base"] == error
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_HOST: VEDO_HOST,
CONF_PORT: VEDO_PORT,
CONF_PIN: VEDO_PIN,
CONF_TYPE: VEDO,
},
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert result["errors"] == {"base": error}
mock_vedo.login.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_HOST: VEDO_HOST,
CONF_PORT: VEDO_PORT,
CONF_PIN: VEDO_PIN,
CONF_TYPE: VEDO,
},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == VEDO_HOST
assert result["data"] == {
CONF_HOST: VEDO_HOST,
CONF_PORT: VEDO_PORT,
CONF_PIN: VEDO_PIN,
CONF_TYPE: VEDO,
}
async def test_reauth_successful(hass: HomeAssistant) -> None:
async def test_reauth_successful(
hass: HomeAssistant,
mock_vedo: AsyncMock,
mock_vedo_config_entry: MockConfigEntry,
) -> None:
"""Test starting a reauthentication flow."""
mock_config = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_BRIDGE_DATA)
mock_config.add_to_hass(hass)
result = await mock_config.start_reauth_flow(hass)
mock_vedo_config_entry.add_to_hass(hass)
result = await mock_vedo_config_entry.start_reauth_flow(hass)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reauth_confirm"
with (
patch(
"aiocomelit.api.ComeliteSerialBridgeApi.login",
),
patch(
"aiocomelit.api.ComeliteSerialBridgeApi.logout",
),
patch("homeassistant.components.comelit.async_setup_entry"),
patch("requests.get") as mock_request_get,
):
mock_request_get.return_value.status_code = 200
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_PIN: FAKE_PIN,
},
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_PIN: FAKE_PIN,
},
)
await hass.async_block_till_done()
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(
@ -136,30 +182,40 @@ async def test_reauth_successful(hass: HomeAssistant) -> None:
(ConnectionResetError, "unknown"),
],
)
async def test_reauth_not_successful(hass: HomeAssistant, side_effect, error) -> None:
async def test_reauth_not_successful(
hass: HomeAssistant,
mock_vedo: AsyncMock,
mock_vedo_config_entry: MockConfigEntry,
side_effect: Exception,
error: str,
) -> None:
"""Test starting a reauthentication flow but no connection found."""
mock_config = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_BRIDGE_DATA)
mock_config.add_to_hass(hass)
result = await mock_config.start_reauth_flow(hass)
mock_vedo_config_entry.add_to_hass(hass)
result = await mock_vedo_config_entry.start_reauth_flow(hass)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reauth_confirm"
with (
patch("aiocomelit.api.ComeliteSerialBridgeApi.login", side_effect=side_effect),
patch(
"aiocomelit.api.ComeliteSerialBridgeApi.logout",
),
patch("homeassistant.components.comelit.async_setup_entry"),
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_PIN: FAKE_PIN,
},
)
mock_vedo.login.side_effect = side_effect
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_PIN: FAKE_PIN,
},
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reauth_confirm"
assert result["errors"] is not None
assert result["errors"]["base"] == error
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reauth_confirm"
assert result["errors"] == {"base": error}
mock_vedo.login.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_PIN: VEDO_PIN,
},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reauth_successful"
assert mock_vedo_config_entry.data[CONF_PIN] == VEDO_PIN

View File

@ -2,21 +2,14 @@
from __future__ import annotations
from unittest.mock import patch
from unittest.mock import AsyncMock
from syrupy import SnapshotAssertion
from syrupy.filters import props
from homeassistant.components.comelit.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from .const import (
BRIDGE_DEVICE_QUERY,
MOCK_USER_BRIDGE_DATA,
MOCK_USER_VEDO_DATA,
VEDO_DEVICE_QUERY,
)
from . import setup_integration
from tests.common import MockConfigEntry
from tests.components.diagnostics import get_diagnostics_for_config_entry
@ -25,25 +18,17 @@ from tests.typing import ClientSessionGenerator
async def test_entry_diagnostics_bridge(
hass: HomeAssistant,
mock_serial_bridge: AsyncMock,
mock_serial_bridge_config_entry: MockConfigEntry,
hass_client: ClientSessionGenerator,
snapshot: SnapshotAssertion,
) -> None:
"""Test Bridge config entry diagnostics."""
entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_BRIDGE_DATA)
entry.add_to_hass(hass)
await setup_integration(hass, mock_serial_bridge_config_entry)
with (
patch("aiocomelit.api.ComeliteSerialBridgeApi.login"),
patch(
"aiocomelit.api.ComeliteSerialBridgeApi.get_all_devices",
return_value=BRIDGE_DEVICE_QUERY,
),
):
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert entry.state == ConfigEntryState.LOADED
assert await get_diagnostics_for_config_entry(hass, hass_client, entry) == snapshot(
assert await get_diagnostics_for_config_entry(
hass, hass_client, mock_serial_bridge_config_entry
) == snapshot(
exclude=props(
"entry_id",
"created_at",
@ -54,25 +39,17 @@ async def test_entry_diagnostics_bridge(
async def test_entry_diagnostics_vedo(
hass: HomeAssistant,
mock_vedo: AsyncMock,
mock_vedo_config_entry: MockConfigEntry,
hass_client: ClientSessionGenerator,
snapshot: SnapshotAssertion,
) -> None:
"""Test Vedo System config entry diagnostics."""
entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_VEDO_DATA)
entry.add_to_hass(hass)
await setup_integration(hass, mock_vedo_config_entry)
with (
patch("aiocomelit.api.ComelitVedoApi.login"),
patch(
"aiocomelit.api.ComelitVedoApi.get_all_areas_and_zones",
return_value=VEDO_DEVICE_QUERY,
),
):
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert entry.state == ConfigEntryState.LOADED
assert await get_diagnostics_for_config_entry(hass, hass_client, entry) == snapshot(
assert await get_diagnostics_for_config_entry(
hass, hass_client, mock_vedo_config_entry
) == snapshot(
exclude=props(
"entry_id",
"created_at",