Sanjay Govind dba4c197c8
Add bosch_alarm integration (#138497)
* Add bosch_alarm integration

* Remove other platforms for now

* update some strings not being consistant

* fix sentence-casing for strings

* remove options flow and versioning

* clean up config flow

* Add OSI license + tagged releases + ci to bosch-alarm-mode2

* Apply suggestions from code review

Co-authored-by: Josef Zweck <josef@zweck.dev>

* apply changes from review

* apply changes from review

* remove options flow

* work on fixtures

* work on fixtures

* fix errors and complete flow

* use fixtures for alarm config

* Update homeassistant/components/bosch_alarm/manifest.json

Co-authored-by: Josef Zweck <josef@zweck.dev>

* fix missing type

* mock setup entry

* remove use of patch in config flow test

* Use coordinator for managing panel data

* Use coordinator for managing panel data

* Coordinator cleanup

* remove unnecessary observers

* update listeners when error state changes

* Update homeassistant/components/bosch_alarm/coordinator.py

Co-authored-by: Josef Zweck <josef@zweck.dev>

* Update homeassistant/components/bosch_alarm/quality_scale.yaml

Co-authored-by: Josef Zweck <josef@zweck.dev>

* Update homeassistant/components/bosch_alarm/config_flow.py

Co-authored-by: Josef Zweck <josef@zweck.dev>

* rename config flow

* Update homeassistant/components/bosch_alarm/quality_scale.yaml

Co-authored-by: Josef Zweck <josef@zweck.dev>

* add missing types

* fix quality_scale.yaml

* enable strict typing

* enable strict typing

* Add test for alarm control panel

* add more tests

* add more tests

* Update homeassistant/components/bosch_alarm/coordinator.py

Co-authored-by: Josef Zweck <josef@zweck.dev>

* Update homeassistant/components/bosch_alarm/coordinator.py

Co-authored-by: Josef Zweck <josef@zweck.dev>

* Update homeassistant/components/bosch_alarm/alarm_control_panel.py

Co-authored-by: Josef Zweck <josef@zweck.dev>

* Update homeassistant/components/bosch_alarm/alarm_control_panel.py

Co-authored-by: Josef Zweck <josef@zweck.dev>

* Update homeassistant/components/bosch_alarm/alarm_control_panel.py

Co-authored-by: Josef Zweck <josef@zweck.dev>

* Add snapshot test

* add snapshot test

* add snapshot test

* update quality scale

* update quality scale

* update quality scale

* update quality scale

* Apply suggestions from code review

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* apply changes from code review

* apply changes from code review

* apply changes from code review

* Apply suggestions from code review

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* apply changes from code review

* apply changes from code review

* Fix alarm control panel device name

* Fix

* Fix

* Fix

* Fix

---------

Co-authored-by: Josef Zweck <josef@zweck.dev>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2025-03-26 13:56:44 +01:00

132 lines
3.6 KiB
Python

"""Define fixtures for Bosch Alarm tests."""
from collections.abc import Generator
from typing import Any
from unittest.mock import AsyncMock, patch
from bosch_alarm_mode2.panel import Area
from bosch_alarm_mode2.utils import Observable
import pytest
from homeassistant.components.bosch_alarm.const import (
CONF_INSTALLER_CODE,
CONF_USER_CODE,
DOMAIN,
)
from homeassistant.const import CONF_HOST, CONF_MODEL, CONF_PASSWORD, CONF_PORT
from tests.common import MockConfigEntry
@pytest.fixture(
params=[
"solution_3000",
"amax_3000",
"b5512",
]
)
def model(request: pytest.FixtureRequest) -> Generator[str]:
"""Return every device."""
return request.param
@pytest.fixture
def extra_config_entry_data(
model: str, model_name: str, config_flow_data: dict[str, Any]
) -> dict[str, Any]:
"""Return extra config entry data."""
return {CONF_MODEL: model_name} | config_flow_data
@pytest.fixture
def config_flow_data(model: str) -> dict[str, Any]:
"""Return extra config entry data."""
if model == "solution_3000":
return {CONF_USER_CODE: "1234"}
if model == "amax_3000":
return {CONF_INSTALLER_CODE: "1234", CONF_PASSWORD: "1234567890"}
if model == "b5512":
return {CONF_PASSWORD: "1234567890"}
pytest.fail("Invalid model")
@pytest.fixture
def model_name(model: str) -> str | None:
"""Return extra config entry data."""
return {
"solution_3000": "Solution 3000",
"amax_3000": "AMAX 3000",
"b5512": "B5512 (US1B)",
}.get(model)
@pytest.fixture
def serial_number(model: str) -> str | None:
"""Return extra config entry data."""
if model == "solution_3000":
return "1234567890"
return None
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.bosch_alarm.async_setup_entry",
return_value=True,
) as mock_setup_entry:
yield mock_setup_entry
@pytest.fixture
def area() -> Generator[Area]:
"""Define a mocked area."""
mock = AsyncMock(spec=Area)
mock.name = "Area1"
mock.status_observer = AsyncMock(spec=Observable)
mock.is_triggered.return_value = False
mock.is_disarmed.return_value = True
mock.is_arming.return_value = False
mock.is_pending.return_value = False
mock.is_part_armed.return_value = False
mock.is_all_armed.return_value = False
return mock
@pytest.fixture
def mock_panel(
area: AsyncMock, model_name: str, serial_number: str | None
) -> Generator[AsyncMock]:
"""Define a fixture to set up Bosch Alarm."""
with (
patch(
"homeassistant.components.bosch_alarm.Panel", autospec=True
) as mock_panel,
patch("homeassistant.components.bosch_alarm.config_flow.Panel", new=mock_panel),
):
client = mock_panel.return_value
client.areas = {1: area}
client.model = model_name
client.firmware_version = "1.0.0"
client.serial_number = serial_number
client.connection_status_observer = AsyncMock(spec=Observable)
yield client
@pytest.fixture
def mock_config_entry(
extra_config_entry_data: dict[str, Any], serial_number: str | None
) -> MockConfigEntry:
"""Mock config entry for bosch alarm."""
return MockConfigEntry(
domain=DOMAIN,
unique_id=serial_number,
entry_id="01JQ917ACKQ33HHM7YCFXYZX51",
data={
CONF_HOST: "0.0.0.0",
CONF_PORT: 7700,
CONF_MODEL: "bosch_alarm_test_data.model",
}
| extra_config_entry_data,
)