mirror of
https://github.com/home-assistant/core.git
synced 2026-11-06 13:41:27 -04:00
Add new CentriConnect component (#166933)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
"""Tests for the CentriConnect/MyPropane API integration."""
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def setup_integration(hass: HomeAssistant, config_entry: MockConfigEntry) -> None:
|
||||
"""Set up the CentriConnect/MyPropane integration for testing."""
|
||||
config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@@ -0,0 +1,77 @@
|
||||
"""Common fixtures for the CentriConnect/MyPropane API tests."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from aiocentriconnect import Tank
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.centriconnect.const import DOMAIN
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_PASSWORD, CONF_USERNAME
|
||||
|
||||
from .const import TEST_PASSWORD, TEST_TANK_ID, TEST_TANK_NAME, TEST_USERNAME
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry() -> MockConfigEntry:
|
||||
"""Return a mock config entry."""
|
||||
return MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id=TEST_TANK_ID,
|
||||
data={
|
||||
CONF_DEVICE_ID: TEST_TANK_ID,
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
},
|
||||
title=TEST_TANK_NAME,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_centriconnect_client() -> Generator[AsyncMock]:
|
||||
"""Mock a CentriConnect/MyPropane client."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.centriconnect.coordinator.CentriConnect",
|
||||
autospec=True,
|
||||
) as mock_client,
|
||||
patch(
|
||||
"homeassistant.components.centriconnect.config_flow.CentriConnect",
|
||||
new=mock_client,
|
||||
),
|
||||
):
|
||||
client = mock_client.return_value
|
||||
client.async_get_tank_data.return_value = Tank(
|
||||
{
|
||||
"AlertStatus": "No Alert",
|
||||
"Altitude": 123.456,
|
||||
"BatteryVolts": 4.19,
|
||||
"DeviceID": TEST_TANK_ID,
|
||||
"DeviceName": TEST_TANK_NAME,
|
||||
"DeviceTempCelsius": 17.0,
|
||||
"DeviceTempFahrenheit": 63.0,
|
||||
"LastPostTimeIso": "2026-02-27 22:00:31.000",
|
||||
"Latitude": 40.7128,
|
||||
"Longitude": -74.0060,
|
||||
"NextPostTimeIso": "2026-02-28 10:00:00.000",
|
||||
"SignalQualLTE": -107.0,
|
||||
"SolarVolts": 2.46,
|
||||
"TankLevel": 75.0,
|
||||
"TankSize": 1000,
|
||||
"TankSizeUnit": "Gallons",
|
||||
"VersionHW": "4.1",
|
||||
"VersionLTE": "1.1.2",
|
||||
}
|
||||
)
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
"""Override async_setup_entry."""
|
||||
with patch(
|
||||
"homeassistant.components.centriconnect.async_setup_entry", return_value=True
|
||||
) as mock_setup_entry:
|
||||
yield mock_setup_entry
|
||||
@@ -0,0 +1,7 @@
|
||||
"""Constants for the CentriConnect/MyPropane integration tests."""
|
||||
|
||||
TEST_TANK_ID = "123a4b5c-678d-9e0f-a123-4b567c8d901e"
|
||||
TEST_USERNAME = "12345678-9012-3456-7a89-b012345cde6f"
|
||||
TEST_PASSWORD = "123456"
|
||||
|
||||
TEST_TANK_NAME = "My Tank"
|
||||
@@ -0,0 +1,695 @@
|
||||
# serializer version: 1
|
||||
# name: test_all_entities[sensor.my_tank_alert_status-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'options': list([
|
||||
'no_alert',
|
||||
'low_level',
|
||||
'critical_level',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.my_tank_alert_status',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Alert status',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Alert status',
|
||||
'platform': 'centriconnect',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <CentriConnectSensorType.ALERT_STATUS: 'alert_status'>,
|
||||
'unique_id': '123a4b5c-678d-9e0f-a123-4b567c8d901e_alert_status',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_alert_status-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'enum',
|
||||
'friendly_name': 'My Tank Alert status',
|
||||
'options': list([
|
||||
'no_alert',
|
||||
'low_level',
|
||||
'critical_level',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.my_tank_alert_status',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'no_alert',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_altitude-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'sensor.my_tank_altitude',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Altitude',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 2,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.DISTANCE: 'distance'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Altitude',
|
||||
'platform': 'centriconnect',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <CentriConnectSensorType.ALTITUDE: 'altitude'>,
|
||||
'unique_id': '123a4b5c-678d-9e0f-a123-4b567c8d901e_altitude',
|
||||
'unit_of_measurement': <UnitOfLength.METERS: 'm'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_altitude-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'distance',
|
||||
'friendly_name': 'My Tank Altitude',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfLength.METERS: 'm'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.my_tank_altitude',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '123.456',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_battery-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'sensor.my_tank_battery',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Battery',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.BATTERY: 'battery'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Battery',
|
||||
'platform': 'centriconnect',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <CentriConnectSensorType.BATTERY_LEVEL: 'battery_level'>,
|
||||
'unique_id': '123a4b5c-678d-9e0f-a123-4b567c8d901e_battery_level',
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_battery-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'battery',
|
||||
'friendly_name': 'My Tank Battery',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.my_tank_battery',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '100.0',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_battery_voltage-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'sensor.my_tank_battery_voltage',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Battery voltage',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 0,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.VOLTAGE: 'voltage'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Battery voltage',
|
||||
'platform': 'centriconnect',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <CentriConnectSensorType.BATTERY_VOLTAGE: 'battery_voltage'>,
|
||||
'unique_id': '123a4b5c-678d-9e0f-a123-4b567c8d901e_battery_voltage',
|
||||
'unit_of_measurement': <UnitOfElectricPotential.VOLT: 'V'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_battery_voltage-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'voltage',
|
||||
'friendly_name': 'My Tank Battery voltage',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfElectricPotential.VOLT: 'V'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.my_tank_battery_voltage',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '4.19',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_device_temperature-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'sensor.my_tank_device_temperature',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Device temperature',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Device temperature',
|
||||
'platform': 'centriconnect',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <CentriConnectSensorType.DEVICE_TEMPERATURE: 'device_temperature'>,
|
||||
'unique_id': '123a4b5c-678d-9e0f-a123-4b567c8d901e_device_temperature',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_device_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'temperature',
|
||||
'friendly_name': 'My Tank Device temperature',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.my_tank_device_temperature',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '17.2222222222222',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_lte_signal_level-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'sensor.my_tank_lte_signal_level',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'LTE signal level',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 0,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'LTE signal level',
|
||||
'platform': 'centriconnect',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <CentriConnectSensorType.LTE_SIGNAL_LEVEL: 'lte_signal_level'>,
|
||||
'unique_id': '123a4b5c-678d-9e0f-a123-4b567c8d901e_lte_signal_level',
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_lte_signal_level-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'My Tank LTE signal level',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.my_tank_lte_signal_level',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '47.1428571428571',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_lte_signal_strength-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'sensor.my_tank_lte_signal_strength',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'LTE signal strength',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.SIGNAL_STRENGTH: 'signal_strength'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'LTE signal strength',
|
||||
'platform': 'centriconnect',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <CentriConnectSensorType.LTE_SIGNAL_STRENGTH: 'lte_signal_strength'>,
|
||||
'unique_id': '123a4b5c-678d-9e0f-a123-4b567c8d901e_lte_signal_strength',
|
||||
'unit_of_measurement': 'dBm',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_lte_signal_strength-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'signal_strength',
|
||||
'friendly_name': 'My Tank LTE signal strength',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': 'dBm',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.my_tank_lte_signal_strength',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '-107.0',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_solar_level-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'sensor.my_tank_solar_level',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Solar level',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 0,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Solar level',
|
||||
'platform': 'centriconnect',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <CentriConnectSensorType.SOLAR_LEVEL: 'solar_level'>,
|
||||
'unique_id': '123a4b5c-678d-9e0f-a123-4b567c8d901e_solar_level',
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_solar_level-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'My Tank Solar level',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.my_tank_solar_level',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '94.6153846153846',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_solar_voltage-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'sensor.my_tank_solar_voltage',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Solar voltage',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 0,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.VOLTAGE: 'voltage'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Solar voltage',
|
||||
'platform': 'centriconnect',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <CentriConnectSensorType.SOLAR_VOLTAGE: 'solar_voltage'>,
|
||||
'unique_id': '123a4b5c-678d-9e0f-a123-4b567c8d901e_solar_voltage',
|
||||
'unit_of_measurement': <UnitOfElectricPotential.VOLT: 'V'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_solar_voltage-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'voltage',
|
||||
'friendly_name': 'My Tank Solar voltage',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfElectricPotential.VOLT: 'V'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.my_tank_solar_voltage',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '2.46',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_tank_level-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.my_tank_tank_level',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Tank level',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Tank level',
|
||||
'platform': 'centriconnect',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <CentriConnectSensorType.TANK_LEVEL: 'tank_level'>,
|
||||
'unique_id': '123a4b5c-678d-9e0f-a123-4b567c8d901e_tank_level',
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_tank_level-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'My Tank Tank level',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.my_tank_tank_level',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '75.0',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_tank_remaining_volume-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.my_tank_tank_remaining_volume',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Tank remaining volume',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 2,
|
||||
}),
|
||||
'sensor.private': dict({
|
||||
'suggested_unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.VOLUME_STORAGE: 'volume_storage'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Tank remaining volume',
|
||||
'platform': 'centriconnect',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <CentriConnectSensorType.TANK_REMAINING_VOLUME: 'tank_remaining_volume'>,
|
||||
'unique_id': '123a4b5c-678d-9e0f-a123-4b567c8d901e_tank_remaining_volume',
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_tank_remaining_volume-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'volume_storage',
|
||||
'friendly_name': 'My Tank Tank remaining volume',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.my_tank_tank_remaining_volume',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '2839.058838',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_tank_size-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.my_tank_tank_size',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Tank size',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 2,
|
||||
}),
|
||||
'sensor.private': dict({
|
||||
'suggested_unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.VOLUME_STORAGE: 'volume_storage'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Tank size',
|
||||
'platform': 'centriconnect',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <CentriConnectSensorType.TANK_SIZE: 'tank_size'>,
|
||||
'unique_id': '123a4b5c-678d-9e0f-a123-4b567c8d901e_tank_size',
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.my_tank_tank_size-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'volume_storage',
|
||||
'friendly_name': 'My Tank Tank size',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.my_tank_tank_size',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '3785.411784',
|
||||
})
|
||||
# ---
|
||||
@@ -0,0 +1,153 @@
|
||||
"""Test the CentriConnect/MyPropane API config flow."""
|
||||
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from aiocentriconnect.exceptions import (
|
||||
CentriConnectConnectionError,
|
||||
CentriConnectConnectionTimeoutError,
|
||||
CentriConnectDecodeError,
|
||||
CentriConnectEmptyResponseError,
|
||||
CentriConnectNotFoundError,
|
||||
CentriConnectTooManyRequestsError,
|
||||
)
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.centriconnect.const import DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_USER
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_PASSWORD, CONF_USERNAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
|
||||
from .const import TEST_PASSWORD, TEST_TANK_ID, TEST_TANK_NAME, TEST_USERNAME
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_full_flow(
|
||||
hass: HomeAssistant,
|
||||
mock_centriconnect_client: AsyncMock,
|
||||
mock_setup_entry: AsyncMock,
|
||||
) -> None:
|
||||
"""Test full flow."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {}
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_DEVICE_ID: TEST_TANK_ID,
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
},
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == TEST_TANK_NAME
|
||||
assert result["data"] == {
|
||||
CONF_DEVICE_ID: TEST_TANK_ID,
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
}
|
||||
assert result["result"].unique_id == TEST_TANK_ID
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("exception", "error"),
|
||||
[
|
||||
(CentriConnectNotFoundError, "invalid_auth"),
|
||||
(CentriConnectDecodeError("Oh no!", "Bad response"), "unknown"),
|
||||
(CentriConnectConnectionTimeoutError, "cannot_connect"),
|
||||
(CentriConnectConnectionError, "cannot_connect"),
|
||||
(CentriConnectTooManyRequestsError, "cannot_connect"),
|
||||
(CentriConnectEmptyResponseError, "unknown"),
|
||||
(Exception, "unknown"),
|
||||
],
|
||||
)
|
||||
async def test_form_errors(
|
||||
hass: HomeAssistant,
|
||||
mock_centriconnect_client: AsyncMock,
|
||||
mock_setup_entry: AsyncMock,
|
||||
exception: Exception,
|
||||
error: str,
|
||||
) -> None:
|
||||
"""Test flow errors."""
|
||||
mock_centriconnect_client.async_get_tank_data.side_effect = exception
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {}
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_DEVICE_ID: TEST_TANK_ID,
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
},
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["errors"] == {"base": error}
|
||||
|
||||
# Make sure the config flow tests finish with either an
|
||||
# FlowResultType.CREATE_ENTRY or FlowResultType.ABORT so
|
||||
# we can show the config flow is able to recover from an error.
|
||||
mock_centriconnect_client.async_get_tank_data.side_effect = None
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_DEVICE_ID: TEST_TANK_ID,
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
},
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == TEST_TANK_NAME
|
||||
assert result["data"] == {
|
||||
CONF_DEVICE_ID: TEST_TANK_ID,
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
}
|
||||
assert result["result"].unique_id == TEST_TANK_ID
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_user_flow_already_configured(
|
||||
hass: HomeAssistant,
|
||||
mock_centriconnect_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test that duplicate devices are rejected."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {}
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_DEVICE_ID: TEST_TANK_ID,
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
},
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
@@ -0,0 +1,29 @@
|
||||
"""Tests for the CentriConnect/MyPropane sensor platform."""
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion 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
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_all_entities(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
mock_centriconnect_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test all entities."""
|
||||
with patch("homeassistant.components.centriconnect.PLATFORMS", [Platform.SENSOR]):
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
Reference in New Issue
Block a user