Add sensor tests for APSystems (#117512)

This commit is contained in:
Joost Lekkerkerker 2024-06-21 11:01:42 +02:00 committed by GitHub
parent 54d8ce5ca9
commit 53022df8a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 560 additions and 19 deletions

View File

@ -132,6 +132,7 @@ class ApSystemsSensorWithDescription(
"""Base sensor to be used with description.""" """Base sensor to be used with description."""
entity_description: ApsystemsLocalApiSensorDescription entity_description: ApsystemsLocalApiSensorDescription
_attr_has_entity_name = True
def __init__( def __init__(
self, self,

View File

@ -1 +1,12 @@
"""Tests for the APsystems Local API integration.""" """Tests for the APsystems Local API 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)

View File

@ -1,10 +1,16 @@
"""Common fixtures for the APsystems Local API tests.""" """Common fixtures for the APsystems Local API tests."""
from unittest.mock import AsyncMock, MagicMock, patch from unittest.mock import AsyncMock, patch
from APsystemsEZ1 import ReturnDeviceInfo, ReturnOutputData
import pytest import pytest
from typing_extensions import Generator from typing_extensions import Generator
from homeassistant.components.apsystems.const import DOMAIN
from homeassistant.const import CONF_IP_ADDRESS
from tests.common import MockConfigEntry
@pytest.fixture @pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]: def mock_setup_entry() -> Generator[AsyncMock]:
@ -17,13 +23,45 @@ def mock_setup_entry() -> Generator[AsyncMock]:
@pytest.fixture @pytest.fixture
def mock_apsystems(): def mock_apsystems() -> Generator[AsyncMock, None, None]:
"""Override APsystemsEZ1M.get_device_info() to return MY_SERIAL_NUMBER as the serial number.""" """Mock APSystems lib."""
ret_data = MagicMock() with (
ret_data.deviceId = "MY_SERIAL_NUMBER" patch(
with patch( "homeassistant.components.apsystems.APsystemsEZ1M",
autospec=True,
) as mock_client,
patch(
"homeassistant.components.apsystems.config_flow.APsystemsEZ1M", "homeassistant.components.apsystems.config_flow.APsystemsEZ1M",
return_value=AsyncMock(), new=mock_client,
) as mock_api: ),
mock_api.return_value.get_device_info.return_value = ret_data ):
mock_api = mock_client.return_value
mock_api.get_device_info.return_value = ReturnDeviceInfo(
deviceId="MY_SERIAL_NUMBER",
devVer="1.0.0",
ssid="MY_SSID",
ipAddr="127.0.01",
minPower=0,
maxPower=1000,
)
mock_api.get_output_data.return_value = ReturnOutputData(
p1=2.0,
e1=3.0,
te1=4.0,
p2=5.0,
e2=6.0,
te2=7.0,
)
yield mock_api yield mock_api
@pytest.fixture
def mock_config_entry() -> MockConfigEntry:
"""Mock config entry."""
return MockConfigEntry(
domain=DOMAIN,
data={
CONF_IP_ADDRESS: "127.0.0.1",
},
unique_id="MY_SERIAL_NUMBER",
)

View File

@ -0,0 +1,460 @@
# serializer version: 1
# name: test_all_entities[sensor.mock_title_lifetime_production_of_p1-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.mock_title_lifetime_production_of_p1',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
'original_icon': None,
'original_name': 'Lifetime production of P1',
'platform': 'apsystems',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'lifetime_production_p1',
'unique_id': 'MY_SERIAL_NUMBER_lifetime_production_p1',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
})
# ---
# name: test_all_entities[sensor.mock_title_lifetime_production_of_p1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Mock Title Lifetime production of P1',
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_lifetime_production_of_p1',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '4.0',
})
# ---
# name: test_all_entities[sensor.mock_title_lifetime_production_of_p2-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.mock_title_lifetime_production_of_p2',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
'original_icon': None,
'original_name': 'Lifetime production of P2',
'platform': 'apsystems',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'lifetime_production_p2',
'unique_id': 'MY_SERIAL_NUMBER_lifetime_production_p2',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
})
# ---
# name: test_all_entities[sensor.mock_title_lifetime_production_of_p2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Mock Title Lifetime production of P2',
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_lifetime_production_of_p2',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '7.0',
})
# ---
# name: test_all_entities[sensor.mock_title_power_of_p1-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.mock_title_power_of_p1',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
'original_icon': None,
'original_name': 'Power of P1',
'platform': 'apsystems',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'total_power_p1',
'unique_id': 'MY_SERIAL_NUMBER_total_power_p1',
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
})
# ---
# name: test_all_entities[sensor.mock_title_power_of_p1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'power',
'friendly_name': 'Mock Title Power of P1',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_power_of_p1',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2.0',
})
# ---
# name: test_all_entities[sensor.mock_title_power_of_p2-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.mock_title_power_of_p2',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
'original_icon': None,
'original_name': 'Power of P2',
'platform': 'apsystems',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'total_power_p2',
'unique_id': 'MY_SERIAL_NUMBER_total_power_p2',
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
})
# ---
# name: test_all_entities[sensor.mock_title_power_of_p2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'power',
'friendly_name': 'Mock Title Power of P2',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_power_of_p2',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '5.0',
})
# ---
# name: test_all_entities[sensor.mock_title_production_of_today-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.mock_title_production_of_today',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
'original_icon': None,
'original_name': 'Production of today',
'platform': 'apsystems',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'today_production',
'unique_id': 'MY_SERIAL_NUMBER_today_production',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
})
# ---
# name: test_all_entities[sensor.mock_title_production_of_today-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Mock Title Production of today',
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_production_of_today',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '9.0',
})
# ---
# name: test_all_entities[sensor.mock_title_production_of_today_from_p1-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.mock_title_production_of_today_from_p1',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
'original_icon': None,
'original_name': 'Production of today from P1',
'platform': 'apsystems',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'today_production_p1',
'unique_id': 'MY_SERIAL_NUMBER_today_production_p1',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
})
# ---
# name: test_all_entities[sensor.mock_title_production_of_today_from_p1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Mock Title Production of today from P1',
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_production_of_today_from_p1',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '3.0',
})
# ---
# name: test_all_entities[sensor.mock_title_production_of_today_from_p2-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.mock_title_production_of_today_from_p2',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
'original_icon': None,
'original_name': 'Production of today from P2',
'platform': 'apsystems',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'today_production_p2',
'unique_id': 'MY_SERIAL_NUMBER_today_production_p2',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
})
# ---
# name: test_all_entities[sensor.mock_title_production_of_today_from_p2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Mock Title Production of today from P2',
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_production_of_today_from_p2',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '6.0',
})
# ---
# name: test_all_entities[sensor.mock_title_total_lifetime_production-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.mock_title_total_lifetime_production',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
'original_icon': None,
'original_name': 'Total lifetime production',
'platform': 'apsystems',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'lifetime_production',
'unique_id': 'MY_SERIAL_NUMBER_lifetime_production',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
})
# ---
# name: test_all_entities[sensor.mock_title_total_lifetime_production-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Mock Title Total lifetime production',
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_total_lifetime_production',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '11.0',
})
# ---
# name: test_all_entities[sensor.mock_title_total_power-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.mock_title_total_power',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
'original_icon': None,
'original_name': 'Total power',
'platform': 'apsystems',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'total_power',
'unique_id': 'MY_SERIAL_NUMBER_total_power',
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
})
# ---
# name: test_all_entities[sensor.mock_title_total_power-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'power',
'friendly_name': 'Mock Title Total power',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_total_power',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '7.0',
})
# ---

View File

@ -12,7 +12,7 @@ from tests.common import MockConfigEntry
async def test_form_create_success( async def test_form_create_success(
hass: HomeAssistant, mock_setup_entry, mock_apsystems hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_apsystems: AsyncMock
) -> None: ) -> None:
"""Test we handle creatinw with success.""" """Test we handle creatinw with success."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
@ -28,11 +28,11 @@ async def test_form_create_success(
async def test_form_cannot_connect_and_recover( async def test_form_cannot_connect_and_recover(
hass: HomeAssistant, mock_apsystems: AsyncMock, mock_setup_entry hass: HomeAssistant, mock_apsystems: AsyncMock, mock_setup_entry: AsyncMock
) -> None: ) -> None:
"""Test we handle cannot connect error.""" """Test we handle cannot connect error."""
mock_apsystems.return_value.get_device_info.side_effect = TimeoutError mock_apsystems.get_device_info.side_effect = TimeoutError
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, DOMAIN,
context={"source": SOURCE_USER}, context={"source": SOURCE_USER},
@ -44,7 +44,7 @@ async def test_form_cannot_connect_and_recover(
assert result["type"] is FlowResultType.FORM assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": "cannot_connect"} assert result["errors"] == {"base": "cannot_connect"}
mock_apsystems.return_value.get_device_info.side_effect = None mock_apsystems.get_device_info.side_effect = None
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
@ -58,13 +58,13 @@ async def test_form_cannot_connect_and_recover(
async def test_form_unique_id_already_configured( async def test_form_unique_id_already_configured(
hass: HomeAssistant, mock_setup_entry, mock_apsystems hass: HomeAssistant,
mock_setup_entry: AsyncMock,
mock_apsystems: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None: ) -> None:
"""Test we handle cannot connect error.""" """Test we handle cannot connect error."""
entry = MockConfigEntry( mock_config_entry.add_to_hass(hass)
domain=DOMAIN, data={CONF_IP_ADDRESS: "127.0.0.2"}, unique_id="MY_SERIAL_NUMBER"
)
entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, DOMAIN,

View File

@ -0,0 +1,31 @@
"""Test the APSystem sensor module."""
from unittest.mock import AsyncMock, patch
from syrupy import SnapshotAssertion
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import setup_integration
from tests.common import MockConfigEntry, snapshot_platform
async def test_all_entities(
hass: HomeAssistant,
snapshot: SnapshotAssertion,
mock_apsystems: AsyncMock,
mock_config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test all entities."""
with patch(
"homeassistant.components.apsystems.PLATFORMS",
[Platform.SENSOR],
):
await setup_integration(hass, mock_config_entry)
await snapshot_platform(
hass, entity_registry, snapshot, mock_config_entry.entry_id
)