danielsmyers fa61ad072d
Add Bryant Evolution Integration (#119788)
* Add an integration for Bryant Evolution HVAC systems.

* Update newly created tests so that they pass.

* Improve compliance with home assistant guidelines.

* Added tests

* remove xxx

* Minor test cleanups

* Add a test for reading HVAC actions.

* Update homeassistant/components/bryant_evolution/__init__.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Update homeassistant/components/bryant_evolution/climate.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Update homeassistant/components/bryant_evolution/climate.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Update homeassistant/components/bryant_evolution/climate.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Update homeassistant/components/bryant_evolution/climate.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Update homeassistant/components/bryant_evolution/climate.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Update homeassistant/components/bryant_evolution/config_flow.py

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>

* Address reviewer comments.

* Address additional reviewer comments.

* Use translation for exception error messages.

* Simplify config flow.

* Continue addressing comments

* Use mocking rather than DI to provide a for-test client in tests.

* Fix a failure in test_config_flow.py

* Track host->filename in strings.json.

* Use config entry ID for climate entity unique id

* Guard against fan mode returning None in async_update.

* Move unavailable-client check from climate.py to init.py.

* Improve test coverage

* Bump evolutionhttp version

* Address comments

* update comment

* only have one _can_reach_device fn

* Auto-detect which systems and zones are attached.

* Add support for reconfiguration

* Fix a few review comments

* Introduce multiple devices

* Track evolutionhttp library change that returns additional per-zone information during enumeration

* Move construction of devices to init

* Avoid triplicate writing

* rework tests to use mocks

* Correct attribute name to unbreak test

* Pull magic tuple of system-zone into a constant

* Address some test comments

* Create test_init.py

* simplify test_reconfigure

* Replace disable_auto_entity_update with mocks.

* Update tests/components/bryant_evolution/test_climate.py

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

* Update tests/components/bryant_evolution/test_climate.py

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

* Update tests/components/bryant_evolution/test_config_flow.py

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

* Update homeassistant/components/bryant_evolution/config_flow.py

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

* Update tests/components/bryant_evolution/test_config_flow.py

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

* Update tests/components/bryant_evolution/test_config_flow.py

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

* fix test errors

* do not access runtime_data in tests

* use snapshot_platform and type fixtures

---------

Co-authored-by: Josef Zweck <24647999+zweckj@users.noreply.github.com>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-07-29 11:25:04 +02:00

71 lines
2.5 KiB
Python

"""Common fixtures for the Bryant Evolution tests."""
from collections.abc import Generator, Mapping
from unittest.mock import AsyncMock, patch
from evolutionhttp import BryantEvolutionLocalClient
import pytest
from homeassistant.components.bryant_evolution.const import CONF_SYSTEM_ZONE, DOMAIN
from homeassistant.const import CONF_FILENAME
from homeassistant.core import HomeAssistant
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
from tests.common import MockConfigEntry
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock, None, None]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.bryant_evolution.async_setup_entry", return_value=True
) as mock_setup_entry:
yield mock_setup_entry
DEFAULT_SYSTEM_ZONES = ((1, 1), (1, 2), (2, 3))
"""
A tuple of (system, zone) pairs representing the default system and zone configurations
for the Bryant Evolution integration.
"""
@pytest.fixture(autouse=True)
def mock_evolution_client_factory() -> Generator[AsyncMock, None, None]:
"""Mock an Evolution client."""
with patch(
"evolutionhttp.BryantEvolutionLocalClient.get_client",
austospec=True,
) as mock_get_client:
clients: Mapping[tuple[int, int], AsyncMock] = {}
for system, zone in DEFAULT_SYSTEM_ZONES:
clients[(system, zone)] = AsyncMock(spec=BryantEvolutionLocalClient)
client = clients[system, zone]
client.read_zone_name.return_value = f"System {system} Zone {zone}"
client.read_current_temperature.return_value = 75
client.read_hvac_mode.return_value = ("COOL", False)
client.read_fan_mode.return_value = "AUTO"
client.read_cooling_setpoint.return_value = 72
mock_get_client.side_effect = lambda system, zone, tty: clients[
(system, zone)
]
yield mock_get_client
@pytest.fixture
async def mock_evolution_entry(
hass: HomeAssistant,
mock_evolution_client_factory: AsyncMock,
) -> MockConfigEntry:
"""Configure and return a Bryant evolution integration."""
hass.config.units = US_CUSTOMARY_SYSTEM
entry = MockConfigEntry(
entry_id="01J3XJZSTEF6G5V0QJX6HBC94T", # For determinism in snapshot tests
domain=DOMAIN,
data={CONF_FILENAME: "/dev/ttyUSB0", CONF_SYSTEM_ZONE: [(1, 1)]},
)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
return entry