Add Autarco integration (#121600)

* Init Autarco integration

* Add integration code with tests

* Update every 5 minutes

* Process all feedback from Joost

* Bump lib to v2.0.0

* Add more then one site if present

* Fix issue with entity translation

* Update the test for sensor entities

* Fix round two based on feedback from Joost

* Add autarco to strict typing

* Update tests/components/autarco/test_config_flow.py

* Update tests/components/autarco/test_config_flow.py

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
Klaas Schoute 2024-07-10 23:05:31 +02:00 committed by GitHub
parent abeac3f3aa
commit fce68018b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 790 additions and 0 deletions

View File

@ -97,6 +97,7 @@ homeassistant.components.assist_pipeline.*
homeassistant.components.asterisk_cdr.*
homeassistant.components.asterisk_mbox.*
homeassistant.components.asuswrt.*
homeassistant.components.autarco.*
homeassistant.components.auth.*
homeassistant.components.automation.*
homeassistant.components.awair.*

View File

@ -155,6 +155,8 @@ build.json @home-assistant/supervisor
/tests/components/aurora_abb_powerone/ @davet2001
/homeassistant/components/aussie_broadband/ @nickw444 @Bre77
/tests/components/aussie_broadband/ @nickw444 @Bre77
/homeassistant/components/autarco/ @klaasnicolaas
/tests/components/autarco/ @klaasnicolaas
/homeassistant/components/auth/ @home-assistant/core
/tests/components/auth/ @home-assistant/core
/homeassistant/components/automation/ @home-assistant/core

View File

@ -0,0 +1,49 @@
"""The Autarco integration."""
from __future__ import annotations
import asyncio
from autarco import Autarco
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .coordinator import AutarcoDataUpdateCoordinator
PLATFORMS: list[Platform] = [Platform.SENSOR]
type AutarcoConfigEntry = ConfigEntry[list[AutarcoDataUpdateCoordinator]]
async def async_setup_entry(hass: HomeAssistant, entry: AutarcoConfigEntry) -> bool:
"""Set up Autarco from a config entry."""
client = Autarco(
email=entry.data[CONF_EMAIL],
password=entry.data[CONF_PASSWORD],
session=async_get_clientsession(hass),
)
account_sites = await client.get_account()
coordinators: list[AutarcoDataUpdateCoordinator] = [
AutarcoDataUpdateCoordinator(hass, client, site) for site in account_sites
]
await asyncio.gather(
*[
coordinator.async_config_entry_first_refresh()
for coordinator in coordinators
]
)
entry.runtime_data = coordinators
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True
async def async_unload_entry(hass: HomeAssistant, entry: AutarcoConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View File

@ -0,0 +1,57 @@
"""Config flow for Autarco integration."""
from __future__ import annotations
from typing import Any
from autarco import Autarco, AutarcoAuthenticationError, AutarcoConnectionError
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import DOMAIN
DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_EMAIL): str,
vol.Required(CONF_PASSWORD): str,
}
)
class AutarcoConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Autarco."""
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle the initial step."""
errors: dict[str, str] = {}
if user_input is not None:
self._async_abort_entries_match({CONF_EMAIL: user_input[CONF_EMAIL]})
client = Autarco(
email=user_input[CONF_EMAIL],
password=user_input[CONF_PASSWORD],
session=async_get_clientsession(self.hass),
)
try:
await client.get_account()
except AutarcoAuthenticationError:
errors["base"] = "invalid_auth"
except AutarcoConnectionError:
errors["base"] = "cannot_connect"
else:
return self.async_create_entry(
title=user_input[CONF_EMAIL],
data={
CONF_EMAIL: user_input[CONF_EMAIL],
CONF_PASSWORD: user_input[CONF_PASSWORD],
},
)
return self.async_show_form(
step_id="user",
errors=errors,
data_schema=DATA_SCHEMA,
)

View File

@ -0,0 +1,13 @@
"""Constants for the Autarco integration."""
from __future__ import annotations
from datetime import timedelta
import logging
from typing import Final
DOMAIN: Final = "autarco"
LOGGER = logging.getLogger(__package__)
SCAN_INTERVAL = timedelta(minutes=5)
SENSORS_SOLAR: Final = "solar"

View File

@ -0,0 +1,47 @@
"""Coordinator for Autarco integration."""
from __future__ import annotations
from typing import NamedTuple
from autarco import AccountSite, Autarco, Solar
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .const import DOMAIN, LOGGER, SCAN_INTERVAL
class AutarcoData(NamedTuple):
"""Class for defining data in dict."""
solar: Solar
class AutarcoDataUpdateCoordinator(DataUpdateCoordinator[AutarcoData]):
"""Class to manage fetching Autarco data from the API."""
config_entry: ConfigEntry
def __init__(
self,
hass: HomeAssistant,
client: Autarco,
site: AccountSite,
) -> None:
"""Initialize global Autarco data updater."""
super().__init__(
hass,
LOGGER,
name=DOMAIN,
update_interval=SCAN_INTERVAL,
)
self.client = client
self.site = site
async def _async_update_data(self) -> AutarcoData:
"""Fetch data from Autarco API."""
return AutarcoData(
solar=await self.client.get_solar(self.site.public_key),
)

View File

@ -0,0 +1,9 @@
{
"domain": "autarco",
"name": "Autarco",
"codeowners": ["@klaasnicolaas"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/autarco",
"iot_class": "cloud_polling",
"requirements": ["autarco==2.0.0"]
}

View File

@ -0,0 +1,113 @@
"""Support for Autarco sensors."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from autarco import Solar
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import UnitOfEnergy, UnitOfPower
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import AutarcoConfigEntry
from .const import DOMAIN
from .coordinator import AutarcoDataUpdateCoordinator
@dataclass(frozen=True, kw_only=True)
class AutarcoSolarSensorEntityDescription(SensorEntityDescription):
"""Describes an Autarco sensor entity."""
state: Callable[[Solar], StateType]
SENSORS_SOLAR: tuple[AutarcoSolarSensorEntityDescription, ...] = (
AutarcoSolarSensorEntityDescription(
key="power_production",
translation_key="power_production",
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
state=lambda solar: solar.power_production,
),
AutarcoSolarSensorEntityDescription(
key="energy_production_today",
translation_key="energy_production_today",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state=lambda solar: solar.energy_production_today,
),
AutarcoSolarSensorEntityDescription(
key="energy_production_month",
translation_key="energy_production_month",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state=lambda solar: solar.energy_production_month,
),
AutarcoSolarSensorEntityDescription(
key="energy_production_total",
translation_key="energy_production_total",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state=lambda solar: solar.energy_production_total,
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: AutarcoConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Autarco sensors based on a config entry."""
for coordinator in entry.runtime_data:
async_add_entities(
AutarcoSolarSensorEntity(
coordinator=coordinator,
description=description,
)
for description in SENSORS_SOLAR
)
class AutarcoSolarSensorEntity(
CoordinatorEntity[AutarcoDataUpdateCoordinator], SensorEntity
):
"""Defines an Autarco solar sensor."""
entity_description: AutarcoSolarSensorEntityDescription
_attr_has_entity_name = True
def __init__(
self,
*,
coordinator: AutarcoDataUpdateCoordinator,
description: AutarcoSolarSensorEntityDescription,
) -> None:
"""Initialize Autarco sensor."""
super().__init__(coordinator)
self.entity_description = description
self._attr_unique_id = f"{coordinator.site.site_id}_solar_{description.key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, f"{coordinator.site.site_id}_solar")},
entry_type=DeviceEntryType.SERVICE,
manufacturer="Autarco",
name="Solar",
)
@property
def native_value(self) -> StateType:
"""Return the state of the sensor."""
return self.entity_description.state(self.coordinator.data.solar)

View File

@ -0,0 +1,40 @@
{
"config": {
"step": {
"user": {
"description": "Connect to your Autarco account to get information about your solar panels.",
"data": {
"email": "[%key:common::config_flow::data::email%]",
"password": "[%key:common::config_flow::data::password%]"
},
"data_description": {
"email": "The email address of your Autarco account.",
"password": "The password of your Autarco account."
}
}
},
"error": {
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
}
},
"entity": {
"sensor": {
"power_production": {
"name": "Power production"
},
"energy_production_today": {
"name": "Energy production today"
},
"energy_production_month": {
"name": "Energy production month"
},
"energy_production_total": {
"name": "ENergy production total"
}
}
}
}

View File

@ -69,6 +69,7 @@ FLOWS = {
"aurora",
"aurora_abb_powerone",
"aussie_broadband",
"autarco",
"awair",
"axis",
"azure_data_explorer",

View File

@ -581,6 +581,12 @@
"config_flow": true,
"iot_class": "cloud_polling"
},
"autarco": {
"name": "Autarco",
"integration_type": "hub",
"config_flow": true,
"iot_class": "cloud_polling"
},
"avion": {
"name": "Avi-on",
"integration_type": "hub",

View File

@ -732,6 +732,16 @@ disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.autarco.*]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.auth.*]
check_untyped_defs = true
disallow_incomplete_defs = true

View File

@ -516,6 +516,9 @@ auroranoaa==0.0.3
# homeassistant.components.aurora_abb_powerone
aurorapy==0.2.7
# homeassistant.components.autarco
autarco==2.0.0
# homeassistant.components.avea
# avea==1.5.1

View File

@ -462,6 +462,9 @@ auroranoaa==0.0.3
# homeassistant.components.aurora_abb_powerone
aurorapy==0.2.7
# homeassistant.components.autarco
autarco==2.0.0
# homeassistant.components.axis
axis==62

View File

@ -0,0 +1,12 @@
"""Tests for the Autarco 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 integration."""
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)

View File

@ -0,0 +1,66 @@
"""Common fixtures for the Autarco tests."""
from collections.abc import Generator
from unittest.mock import AsyncMock, patch
from autarco import AccountSite, Solar
import pytest
from homeassistant.components.autarco.const import DOMAIN
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
from tests.common import MockConfigEntry
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.autarco.async_setup_entry", return_value=True
) as mock_setup_entry:
yield mock_setup_entry
@pytest.fixture
def mock_autarco_client() -> Generator[AsyncMock]:
"""Mock a Autarco client."""
with (
patch(
"homeassistant.components.autarco.Autarco",
autospec=True,
) as mock_client,
patch(
"homeassistant.components.autarco.config_flow.Autarco",
new=mock_client,
),
):
client = mock_client.return_value
client.get_account.return_value = [
AccountSite(
site_id=1,
public_key="key-public",
system_name="test-system",
retailer="test-retailer",
health="OK",
)
]
client.get_solar.return_value = Solar(
power_production=200,
energy_production_today=4,
energy_production_month=58,
energy_production_total=10379,
)
yield client
@pytest.fixture
def mock_config_entry() -> MockConfigEntry:
"""Mock a config entry."""
return MockConfigEntry(
domain=DOMAIN,
title="Autarco",
data={
CONF_EMAIL: "test@autarco.com",
CONF_PASSWORD: "test-password",
},
)

View File

@ -0,0 +1,6 @@
{
"pv_now": 200,
"pv_today": 4,
"pv_month": 58,
"pv_to_date": 10379
}

View File

@ -0,0 +1,196 @@
# serializer version: 1
# name: test_solar_sensors[sensor.solar_energy_production_month-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.solar_energy_production_month',
'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': 'Energy production month',
'platform': 'autarco',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'energy_production_month',
'unique_id': '1_solar_energy_production_month',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
})
# ---
# name: test_solar_sensors[sensor.solar_energy_production_month-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Solar Energy production month',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
}),
'context': <ANY>,
'entity_id': 'sensor.solar_energy_production_month',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '58',
})
# ---
# name: test_solar_sensors[sensor.solar_energy_production_today-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.solar_energy_production_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': 'Energy production today',
'platform': 'autarco',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'energy_production_today',
'unique_id': '1_solar_energy_production_today',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
})
# ---
# name: test_solar_sensors[sensor.solar_energy_production_today-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Solar Energy production today',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
}),
'context': <ANY>,
'entity_id': 'sensor.solar_energy_production_today',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '4',
})
# ---
# name: test_solar_sensors[sensor.solar_energy_production_total-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.solar_energy_production_total',
'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': 'ENergy production total',
'platform': 'autarco',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'energy_production_total',
'unique_id': '1_solar_energy_production_total',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
})
# ---
# name: test_solar_sensors[sensor.solar_energy_production_total-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Solar ENergy production total',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
}),
'context': <ANY>,
'entity_id': 'sensor.solar_energy_production_total',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '10379',
})
# ---
# name: test_solar_sensors[sensor.solar_power_production-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.solar_power_production',
'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 production',
'platform': 'autarco',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'power_production',
'unique_id': '1_solar_power_production',
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
})
# ---
# name: test_solar_sensors[sensor.solar_power_production-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'power',
'friendly_name': 'Solar Power production',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
}),
'context': <ANY>,
'entity_id': 'sensor.solar_power_production',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '200',
})
# ---

View File

@ -0,0 +1,101 @@
"""Test the Autarco config flow."""
from unittest.mock import AsyncMock
from autarco import AutarcoAuthenticationError, AutarcoConnectionError
import pytest
from homeassistant.components.autarco.const import DOMAIN
from homeassistant.config_entries import SOURCE_USER
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from tests.common import MockConfigEntry
async def test_full_user_flow(
hass: HomeAssistant,
mock_autarco_client: AsyncMock,
mock_setup_entry: AsyncMock,
) -> None:
"""Test the full user configuration flow."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result.get("type") is FlowResultType.FORM
assert result.get("step_id") == "user"
assert not result.get("errors")
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={CONF_EMAIL: "test@autarco.com", CONF_PASSWORD: "test-password"},
)
assert result.get("type") is FlowResultType.CREATE_ENTRY
assert result.get("title") == "test@autarco.com"
assert result.get("data") == {
CONF_EMAIL: "test@autarco.com",
CONF_PASSWORD: "test-password",
}
assert len(mock_autarco_client.get_account.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1
async def test_duplicate_entry(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_autarco_client: AsyncMock,
) -> None:
"""Test abort when setting up duplicate entry."""
mock_config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result.get("type") is FlowResultType.FORM
assert not result.get("errors")
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={CONF_EMAIL: "test@autarco.com", CONF_PASSWORD: "test-password"},
)
assert result.get("type") is FlowResultType.ABORT
assert result.get("reason") == "already_configured"
@pytest.mark.parametrize(
("exception", "error"),
[
(AutarcoConnectionError, "cannot_connect"),
(AutarcoAuthenticationError, "invalid_auth"),
],
)
async def test_exceptions(
hass: HomeAssistant,
mock_autarco_client: AsyncMock,
mock_setup_entry: AsyncMock,
exception: Exception,
error: str,
) -> None:
"""Test exceptions."""
mock_autarco_client.get_account.side_effect = exception
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={CONF_EMAIL: "test@autarco.com", CONF_PASSWORD: "test-password"},
)
assert result.get("type") is FlowResultType.FORM
assert result.get("errors") == {"base": error}
mock_autarco_client.get_account.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={CONF_EMAIL: "test@autarco.com", CONF_PASSWORD: "test-password"},
)
assert result.get("type") is FlowResultType.CREATE_ENTRY

View File

@ -0,0 +1,28 @@
"""Test the Autarco init module."""
from __future__ import annotations
from unittest.mock import AsyncMock
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from . import setup_integration
from tests.common import MockConfigEntry
async def test_load_unload_entry(
hass: HomeAssistant,
mock_autarco_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test load and unload entry."""
await setup_integration(hass, mock_config_entry)
assert mock_config_entry.state is ConfigEntryState.LOADED
await hass.config_entries.async_remove(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED

View File

@ -0,0 +1,27 @@
"""Test the sensor provided by the Autarco integration."""
from unittest.mock import MagicMock, 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_solar_sensors(
hass: HomeAssistant,
mock_autarco_client: MagicMock,
mock_config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
) -> None:
"""Test the Autarco - Solar sensor."""
with patch("homeassistant.components.autarco.PLATFORMS", [Platform.SENSOR]):
await setup_integration(hass, mock_config_entry)
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)