1
0
mirror of https://github.com/home-assistant/core.git synced 2026-05-23 17:00:13 +01:00
Files
core/tests/components/indevolt/test_sensor.py
T
2026-05-18 12:32:37 +02:00

222 lines
7.2 KiB
Python

"""Tests for the Indevolt sensor platform."""
from datetime import timedelta
from unittest.mock import AsyncMock, patch
from freezegun.api import FrozenDateTimeFactory
from indevolt_api import IndevoltConfig, IndevoltEnergyMode
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.indevolt.coordinator import SCAN_INTERVAL
from homeassistant.const import STATE_UNAVAILABLE, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er
from . import setup_integration
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
@pytest.mark.parametrize("generation", [2, 1], indirect=True)
async def test_sensor(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
mock_indevolt: AsyncMock,
snapshot: SnapshotAssertion,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test sensor registration for sensors."""
with patch("homeassistant.components.indevolt.PLATFORMS", [Platform.SENSOR]):
await setup_integration(hass, mock_config_entry)
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
@pytest.mark.parametrize("generation", [2], indirect=True)
async def test_sensor_availability(
hass: HomeAssistant,
mock_indevolt: AsyncMock,
mock_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test sensor availability / non-availability."""
with patch("homeassistant.components.indevolt.PLATFORMS", [Platform.SENSOR]):
await setup_integration(hass, mock_config_entry)
assert (state := hass.states.get("sensor.cms_sf2000_battery_soc"))
assert state.state == "92"
mock_indevolt.fetch_data.side_effect = ConnectionError
freezer.tick(delta=timedelta(seconds=SCAN_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert (state := hass.states.get("sensor.cms_sf2000_battery_soc"))
assert state.state == STATE_UNAVAILABLE
@pytest.mark.parametrize("generation", [2], indirect=True)
async def test_realtime_sensor_energy_mode_availability(
hass: HomeAssistant,
mock_indevolt: AsyncMock,
mock_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test real-time sensors are only available in real-time control energy mode."""
with patch("homeassistant.components.indevolt.PLATFORMS", [Platform.SENSOR]):
await setup_integration(hass, mock_config_entry)
# Default fixture is not in RT mode (1), sensors should be unavailable
assert (
hass.states.get("sensor.cms_sf2000_real_time_mode").state == STATE_UNAVAILABLE
)
assert (
hass.states.get("sensor.cms_sf2000_real_time_target_soc").state
== STATE_UNAVAILABLE
)
assert (
hass.states.get("sensor.cms_sf2000_real_time_power_limit").state
== STATE_UNAVAILABLE
)
# Switch to RT mode (4), sensors should be available
mock_indevolt.fetch_data.return_value[IndevoltConfig.READ_ENERGY_MODE] = (
IndevoltEnergyMode.REAL_TIME_CONTROL
)
freezer.tick(delta=timedelta(seconds=SCAN_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert hass.states.get("sensor.cms_sf2000_real_time_mode").state == "standby"
assert hass.states.get("sensor.cms_sf2000_real_time_target_soc").state == "80"
assert hass.states.get("sensor.cms_sf2000_real_time_power_limit").state == "200"
# Switch back to a non-RT mode (0), sensors become unavailable again
mock_indevolt.fetch_data.return_value[IndevoltConfig.READ_ENERGY_MODE] = (
IndevoltEnergyMode.OUTDOOR_PORTABLE
)
freezer.tick(delta=timedelta(seconds=SCAN_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert (
hass.states.get("sensor.cms_sf2000_real_time_mode").state == STATE_UNAVAILABLE
)
assert (
hass.states.get("sensor.cms_sf2000_real_time_target_soc").state
== STATE_UNAVAILABLE
)
assert (
hass.states.get("sensor.cms_sf2000_real_time_power_limit").state
== STATE_UNAVAILABLE
)
# In individual tests, you can override the mock behavior
async def test_battery_pack_filtering(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_indevolt: AsyncMock,
entity_registry: er.EntityRegistry,
) -> None:
"""Test that battery pack sensors are filtered based on SN availability."""
# Mock battery pack data - only first two packs have SNs
mock_indevolt.fetch_data.return_value = {
"9032": "BAT001",
"9051": "BAT002",
"9070": None,
"9165": "",
"9218": None,
}
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
# Get all sensor entities
entity_entries = er.async_entries_for_config_entry(
entity_registry, mock_config_entry.entry_id
)
# Verify sensors for packs 1 and 2 exist (with SNs)
pack1_sensors = [
e
for e in entity_entries
if any(key in e.unique_id for key in ("9032", "9016", "9030", "9020", "19173"))
]
pack2_sensors = [
e
for e in entity_entries
if any(key in e.unique_id for key in ("9051", "9035", "9049", "9039", "19174"))
]
assert len(pack1_sensors) == 5
assert len(pack2_sensors) == 5
# Verify sensors for packs 3, 4, and 5 don't exist (no SNs)
pack3_sensors = [
e
for e in entity_entries
if any(key in e.unique_id for key in ("9070", "9054", "9068", "9058", "19175"))
]
pack4_sensors = [
e
for e in entity_entries
if any(key in e.unique_id for key in ("9165", "9149", "9163", "9153", "19176"))
]
pack5_sensors = [
e
for e in entity_entries
if any(key in e.unique_id for key in ("9218", "9202", "9216", "9206", "19177"))
]
assert len(pack3_sensors) == 0
assert len(pack4_sensors) == 0
assert len(pack5_sensors) == 0
async def test_battery_pack_filtering_fetch_error(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_indevolt: AsyncMock,
entity_registry: er.EntityRegistry,
) -> None:
"""Test battery pack filtering when fetch fails."""
# Mock fetch_data to raise error on battery pack SN fetch
mock_indevolt.fetch_data.side_effect = HomeAssistantError("Timeout")
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
# Get all sensor entities
entity_entries = er.async_entries_for_config_entry(
entity_registry, mock_config_entry.entry_id
)
# Verify sensors (no sensors)
battery_pack_keys = [
"9032",
"9051",
"9070",
"9165",
"9218",
"9016",
"9035",
"9054",
"9149",
"9202",
]
battery_sensors = [
e
for e in entity_entries
if any(key in e.unique_id for key in battery_pack_keys)
]
assert len(battery_sensors) == 0