Files
core/tests/components/sunsynk/test_sensor.py
T
2026-08-30 16:44:15 +02:00

129 lines
4.9 KiB
Python

"""Test the Sunsynk sensors."""
from unittest.mock import AsyncMock
from freezegun.api import FrozenDateTimeFactory
import pytest
from sunsynk.exceptions import SunsynkConnectionError
from sunsynk.grid import Grid
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.sunsynk.const import DOMAIN, SCAN_INTERVAL
from homeassistant.const import STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from . import setup_integration
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
ENTITY_ID_GRID_POWER = "sensor.garage_inverter_grid_power"
ENTITY_ID_GRID_POWER_2 = "sensor.inverter_2938475610_grid_power"
@pytest.mark.usefixtures("mock_sunsynk_client", "entity_registry_enabled_by_default")
async def test_sensors(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
) -> None:
"""Test the sensor entities."""
await setup_integration(hass, mock_config_entry)
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
async def test_sensors_unavailable_on_error(
hass: HomeAssistant,
mock_sunsynk_client: AsyncMock,
mock_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test the sensors become unavailable when an update fails."""
await setup_integration(hass, mock_config_entry)
assert hass.states.get(ENTITY_ID_GRID_POWER).state == "610.0"
grid = mock_sunsynk_client.get_inverter_realtime_grid.side_effect
mock_sunsynk_client.get_inverter_realtime_grid.side_effect = SunsynkConnectionError
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
assert hass.states.get(ENTITY_ID_GRID_POWER).state == STATE_UNAVAILABLE
mock_sunsynk_client.get_inverter_realtime_grid.side_effect = grid
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
assert hass.states.get(ENTITY_ID_GRID_POWER).state == "610.0"
async def test_one_inverter_unavailable(
hass: HomeAssistant,
mock_sunsynk_client: AsyncMock,
mock_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test a failing inverter does not affect the other inverters."""
await setup_integration(hass, mock_config_entry)
assert hass.states.get(ENTITY_ID_GRID_POWER).state == "610.0"
assert hass.states.get(ENTITY_ID_GRID_POWER_2).state == "610.0"
grid = mock_sunsynk_client.get_inverter_realtime_grid.side_effect
def failing_grid(sn: str) -> Grid:
if sn == "2938475610":
raise SunsynkConnectionError
return grid(sn)
mock_sunsynk_client.get_inverter_realtime_grid.side_effect = failing_grid
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
assert hass.states.get(ENTITY_ID_GRID_POWER).state == "610.0"
assert hass.states.get(ENTITY_ID_GRID_POWER_2).state == STATE_UNAVAILABLE
mock_sunsynk_client.get_inverter_realtime_grid.side_effect = grid
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
assert hass.states.get(ENTITY_ID_GRID_POWER_2).state == "610.0"
@pytest.mark.usefixtures("mock_sunsynk_client")
async def test_power_sensors_use_total_of_all_phases(
hass: HomeAssistant, mock_config_entry: MockConfigEntry
) -> None:
"""Test the grid and load power sensors report the total across all phases."""
await setup_integration(hass, mock_config_entry)
assert hass.states.get(ENTITY_ID_GRID_POWER).state == "610.0"
assert hass.states.get("sensor.garage_inverter_load_power").state == "3427.0"
@pytest.mark.usefixtures("mock_sunsynk_client")
async def test_no_battery(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
device_registry: dr.DeviceRegistry,
) -> None:
"""Test an inverter without a battery gets no battery device or entities."""
await setup_integration(hass, mock_config_entry)
entry_id = mock_config_entry.entry_id
inverter = device_registry.async_get_device_by_identifier(
(DOMAIN, "1029384756"), entry_id
)
battery = device_registry.async_get_device_by_identifier(
(DOMAIN, "1029384756_battery"), entry_id
)
assert inverter is not None
assert battery is not None
assert battery.via_device_id == inverter.id
assert hass.states.get("sensor.battery_1029384756_state_of_charge").state == "20.0"
assert (
device_registry.async_get_device_by_identifier(
(DOMAIN, "2938475610_battery"), entry_id
)
is None
)
assert hass.states.get("sensor.battery_2938475610_state_of_charge") is None