Bump sunweg to 2.0.1 (#105613)

* chore(sunweg): minor requested changes

* test(sunweg): use of fixtures

* feat(sunweg): provide bad auth result on expired authentication

* chore(sunweg): bump version

* chore(sunweg): removed reauth

* chore(sunweg): removed features out of scope

* chore(sunweg): fixtures moved to conftest.py

* chore(sunweg): devicetype moved to const

* chore(sunweg):  conftest comment

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
Lucas Mindêllo de Andrade 2023-12-14 12:51:57 -03:00 committed by GitHub
parent 7e1dc2286f
commit d4a7361bc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 191 additions and 152 deletions

View File

@ -13,7 +13,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import StateType from homeassistant.helpers.typing import StateType
from homeassistant.util import Throttle from homeassistant.util import Throttle
from .const import CONF_PLANT_ID, DOMAIN, PLATFORMS from .const import CONF_PLANT_ID, DOMAIN, PLATFORMS, DeviceType
from .sensor_types.sensor_entity_description import SunWEGSensorEntityDescription from .sensor_types.sensor_entity_description import SunWEGSensorEntityDescription
SCAN_INTERVAL = datetime.timedelta(minutes=5) SCAN_INTERVAL = datetime.timedelta(minutes=5)
@ -74,12 +74,12 @@ class SunWEGData:
def get_api_value( def get_api_value(
self, self,
variable: str, variable: str,
device_type: str, device_type: DeviceType,
inverter_id: int = 0, inverter_id: int = 0,
deep_name: str | None = None, deep_name: str | None = None,
): ):
"""Retrieve from a Plant the desired variable value.""" """Retrieve from a Plant the desired variable value."""
if device_type == "total": if device_type == DeviceType.TOTAL:
return self.data.__dict__.get(variable) return self.data.__dict__.get(variable)
inverter_list = [i for i in self.data.inverters if i.id == inverter_id] inverter_list = [i for i in self.data.inverters if i.id == inverter_id]
@ -87,13 +87,13 @@ class SunWEGData:
return None return None
inverter = inverter_list[0] inverter = inverter_list[0]
if device_type == "inverter": if device_type == DeviceType.INVERTER:
return inverter.__dict__.get(variable) return inverter.__dict__.get(variable)
if device_type == "phase": if device_type == DeviceType.PHASE:
for phase in inverter.phases: for phase in inverter.phases:
if phase.name == deep_name: if phase.name == deep_name:
return phase.__dict__.get(variable) return phase.__dict__.get(variable)
elif device_type == "string": elif device_type == DeviceType.STRING:
for mppt in inverter.mppts: for mppt in inverter.mppts:
for string in mppt.strings: for string in mppt.strings:
if string.name == deep_name: if string.name == deep_name:
@ -103,7 +103,7 @@ class SunWEGData:
def get_data( def get_data(
self, self,
entity_description: SunWEGSensorEntityDescription, entity_description: SunWEGSensorEntityDescription,
device_type: str, device_type: DeviceType,
inverter_id: int = 0, inverter_id: int = 0,
deep_name: str | None = None, deep_name: str | None = None,
) -> StateType | datetime.datetime: ) -> StateType | datetime.datetime:
@ -113,13 +113,13 @@ class SunWEGData:
entity_description.name, entity_description.name,
) )
variable = entity_description.api_variable_key variable = entity_description.api_variable_key
previous_metric = entity_description.native_unit_of_measurement previous_unit = entity_description.native_unit_of_measurement
api_value = self.get_api_value(variable, device_type, inverter_id, deep_name) api_value = self.get_api_value(variable, device_type, inverter_id, deep_name)
previous_value = self.previous_values.get(variable) previous_value = self.previous_values.get(variable)
return_value = api_value return_value = api_value
if entity_description.api_variable_metric is not None: if entity_description.api_variable_unit is not None:
entity_description.native_unit_of_measurement = self.get_api_value( entity_description.native_unit_of_measurement = self.get_api_value(
entity_description.api_variable_metric, entity_description.api_variable_unit,
device_type, device_type,
inverter_id, inverter_id,
deep_name, deep_name,
@ -130,7 +130,7 @@ class SunWEGData:
entity_description.previous_value_drop_threshold is not None entity_description.previous_value_drop_threshold is not None
and previous_value is not None and previous_value is not None
and api_value is not None and api_value is not None
and previous_metric == entity_description.native_unit_of_measurement and previous_unit == entity_description.native_unit_of_measurement
): ):
_LOGGER.debug( _LOGGER.debug(
( (

View File

@ -1,6 +1,18 @@
"""Define constants for the Sun WEG component.""" """Define constants for the Sun WEG component."""
from enum import Enum
from homeassistant.const import Platform from homeassistant.const import Platform
class DeviceType(Enum):
"""Device Type Enum."""
TOTAL = 1
INVERTER = 2
PHASE = 3
STRING = 4
CONF_PLANT_ID = "plant_id" CONF_PLANT_ID = "plant_id"
DEFAULT_PLANT_ID = 0 DEFAULT_PLANT_ID = 0

View File

@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/sunweg/", "documentation": "https://www.home-assistant.io/integrations/sunweg/",
"iot_class": "cloud_polling", "iot_class": "cloud_polling",
"loggers": ["sunweg"], "loggers": ["sunweg"],
"requirements": ["sunweg==2.0.0"] "requirements": ["sunweg==2.0.1"]
} }

View File

@ -19,7 +19,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType from homeassistant.helpers.typing import StateType
from . import SunWEGData from . import SunWEGData
from .const import CONF_PLANT_ID, DEFAULT_PLANT_ID, DOMAIN from .const import CONF_PLANT_ID, DEFAULT_PLANT_ID, DOMAIN, DeviceType
from .sensor_types.inverter import INVERTER_SENSOR_TYPES from .sensor_types.inverter import INVERTER_SENSOR_TYPES
from .sensor_types.phase import PHASE_SENSOR_TYPES from .sensor_types.phase import PHASE_SENSOR_TYPES
from .sensor_types.sensor_entity_description import SunWEGSensorEntityDescription from .sensor_types.sensor_entity_description import SunWEGSensorEntityDescription
@ -67,7 +67,7 @@ async def async_setup_entry(
name=f"{name} Total", name=f"{name} Total",
unique_id=f"{plant_id}-{description.key}", unique_id=f"{plant_id}-{description.key}",
description=description, description=description,
device_type="total", device_type=DeviceType.TOTAL,
) )
for description in TOTAL_SENSOR_TYPES for description in TOTAL_SENSOR_TYPES
] ]
@ -80,7 +80,7 @@ async def async_setup_entry(
name=f"{device.name}", name=f"{device.name}",
unique_id=f"{device.sn}-{description.key}", unique_id=f"{device.sn}-{description.key}",
description=description, description=description,
device_type="inverter", device_type=DeviceType.INVERTER,
inverter_id=device.id, inverter_id=device.id,
) )
for device in devices for device in devices
@ -96,7 +96,7 @@ async def async_setup_entry(
unique_id=f"{device.sn}-{phase.name}-{description.key}", unique_id=f"{device.sn}-{phase.name}-{description.key}",
description=description, description=description,
inverter_id=device.id, inverter_id=device.id,
device_type="phase", device_type=DeviceType.PHASE,
deep_name=phase.name, deep_name=phase.name,
) )
for device in devices for device in devices
@ -113,7 +113,7 @@ async def async_setup_entry(
unique_id=f"{device.sn}-{string.name}-{description.key}", unique_id=f"{device.sn}-{string.name}-{description.key}",
description=description, description=description,
inverter_id=device.id, inverter_id=device.id,
device_type="string", device_type=DeviceType.STRING,
deep_name=string.name, deep_name=string.name,
) )
for device in devices for device in devices
@ -137,7 +137,7 @@ class SunWEGInverter(SensorEntity):
name: str, name: str,
unique_id: str, unique_id: str,
description: SunWEGSensorEntityDescription, description: SunWEGSensorEntityDescription,
device_type: str, device_type: DeviceType,
inverter_id: int = 0, inverter_id: int = 0,
deep_name: str | None = None, deep_name: str | None = None,
) -> None: ) -> None:

View File

@ -16,7 +16,7 @@ INVERTER_SENSOR_TYPES: tuple[SunWEGSensorEntityDescription, ...] = (
key="inverter_energy_today", key="inverter_energy_today",
name="Energy today", name="Energy today",
api_variable_key="_today_energy", api_variable_key="_today_energy",
api_variable_metric="_today_energy_metric", api_variable_unit="_today_energy_metric",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY, device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING, state_class=SensorStateClass.TOTAL_INCREASING,
@ -26,7 +26,7 @@ INVERTER_SENSOR_TYPES: tuple[SunWEGSensorEntityDescription, ...] = (
key="inverter_energy_total", key="inverter_energy_total",
name="Lifetime energy output", name="Lifetime energy output",
api_variable_key="_total_energy", api_variable_key="_total_energy",
api_variable_metric="_total_energy_metric", api_variable_unit="_total_energy_metric",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY, device_class=SensorDeviceClass.ENERGY,
suggested_display_precision=1, suggested_display_precision=1,
@ -45,7 +45,7 @@ INVERTER_SENSOR_TYPES: tuple[SunWEGSensorEntityDescription, ...] = (
key="inverter_current_wattage", key="inverter_current_wattage",
name="Output power", name="Output power",
api_variable_key="_power", api_variable_key="_power",
api_variable_metric="_power_metric", api_variable_unit="_power_metric",
native_unit_of_measurement=UnitOfPower.WATT, native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER, device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,

View File

@ -17,7 +17,7 @@ class SunWEGRequiredKeysMixin:
class SunWEGSensorEntityDescription(SensorEntityDescription, SunWEGRequiredKeysMixin): class SunWEGSensorEntityDescription(SensorEntityDescription, SunWEGRequiredKeysMixin):
"""Describes SunWEG sensor entity.""" """Describes SunWEG sensor entity."""
api_variable_metric: str | None = None api_variable_unit: str | None = None
previous_value_drop_threshold: float | None = None previous_value_drop_threshold: float | None = None
never_resets: bool = False never_resets: bool = False
icon: str | None = None icon: str | None = None

View File

@ -19,7 +19,7 @@ TOTAL_SENSOR_TYPES: tuple[SunWEGSensorEntityDescription, ...] = (
key="total_energy_today", key="total_energy_today",
name="Energy Today", name="Energy Today",
api_variable_key="_today_energy", api_variable_key="_today_energy",
api_variable_metric="_today_energy_metric", api_variable_unit="_today_energy_metric",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY, device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING, state_class=SensorStateClass.TOTAL_INCREASING,

View File

@ -2553,7 +2553,7 @@ subarulink==0.7.9
sunwatcher==0.2.1 sunwatcher==0.2.1
# homeassistant.components.sunweg # homeassistant.components.sunweg
sunweg==2.0.0 sunweg==2.0.1
# homeassistant.components.surepetcare # homeassistant.components.surepetcare
surepy==0.8.0 surepy==0.8.0

View File

@ -1917,7 +1917,7 @@ subarulink==0.7.9
sunwatcher==0.2.1 sunwatcher==0.2.1
# homeassistant.components.sunweg # homeassistant.components.sunweg
sunweg==2.0.0 sunweg==2.0.1
# homeassistant.components.surepetcare # homeassistant.components.surepetcare
surepy==0.8.0 surepy==0.8.0

View File

@ -1,57 +1,15 @@
"""Common functions needed to setup tests for Sun WEG.""" """Common functions needed to setup tests for Sun WEG."""
from datetime import datetime
from sunweg.device import MPPT, Inverter, Phase, String
from sunweg.plant import Plant
from homeassistant.components.sunweg.const import CONF_PLANT_ID, DOMAIN from homeassistant.components.sunweg.const import CONF_PLANT_ID, DOMAIN
from homeassistant.const import CONF_NAME, CONF_PASSWORD, CONF_USERNAME from homeassistant.const import CONF_NAME, CONF_PASSWORD, CONF_USERNAME
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
FIXTURE_USER_INPUT = { SUNWEG_USER_INPUT = {
CONF_USERNAME: "username", CONF_USERNAME: "username",
CONF_PASSWORD: "password", CONF_PASSWORD: "password",
} }
SUNWEG_PLANT_RESPONSE = Plant(
123456,
"Plant #123",
29.5,
0.5,
0,
12.786912,
24.0,
"kWh",
332.2,
0.012296,
datetime(2023, 2, 16, 14, 22, 37),
)
SUNWEG_INVERTER_RESPONSE = Inverter(
21255,
"INVERSOR01",
"J63T233018RE074",
23.2,
0.0,
0.0,
"MWh",
0,
"kWh",
0.0,
1,
0,
"kW",
)
SUNWEG_PHASE_RESPONSE = Phase("PhaseA", 120.0, 3.2, 0, 0)
SUNWEG_MPPT_RESPONSE = MPPT("MPPT1")
SUNWEG_STRING_RESPONSE = String("STR1", 450.3, 23.4, 0)
SUNWEG_LOGIN_RESPONSE = True
SUNWEG_MOCK_ENTRY = MockConfigEntry( SUNWEG_MOCK_ENTRY = MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,
data={ data={

View File

@ -0,0 +1,70 @@
"""Conftest for SunWEG tests."""
from datetime import datetime
import pytest
from sunweg.device import MPPT, Inverter, Phase, String
from sunweg.plant import Plant
@pytest.fixture
def string_fixture() -> String:
"""Define String fixture."""
return String("STR1", 450.3, 23.4, 0)
@pytest.fixture
def mppt_fixture(string_fixture) -> MPPT:
"""Define MPPT fixture."""
mppt = MPPT("mppt")
mppt.strings.append(string_fixture)
return mppt
@pytest.fixture
def phase_fixture() -> Phase:
"""Define Phase fixture."""
return Phase("PhaseA", 120.0, 3.2, 0, 0)
@pytest.fixture
def inverter_fixture(phase_fixture, mppt_fixture) -> Inverter:
"""Define inverter fixture."""
inverter = Inverter(
21255,
"INVERSOR01",
"J63T233018RE074",
23.2,
0.0,
0.0,
"MWh",
0,
"kWh",
0.0,
1,
0,
"kW",
)
inverter.phases.append(phase_fixture)
inverter.mppts.append(mppt_fixture)
return inverter
@pytest.fixture
def plant_fixture(inverter_fixture) -> Plant:
"""Define Plant fixture."""
plant = Plant(
123456,
"Plant #123",
29.5,
0.5,
0,
12.786912,
24.0,
"kWh",
332.2,
0.012296,
datetime(2023, 2, 16, 14, 22, 37),
)
plant.inverters.append(inverter_fixture)
return plant

View File

@ -1,5 +1,4 @@
"""Tests for the Sun WEG server config flow.""" """Tests for the Sun WEG server config flow."""
from copy import deepcopy
from unittest.mock import patch from unittest.mock import patch
from sunweg.api import APIHelper from sunweg.api import APIHelper
@ -9,7 +8,7 @@ from homeassistant.components.sunweg.const import CONF_PLANT_ID, DOMAIN
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from .common import FIXTURE_USER_INPUT, SUNWEG_LOGIN_RESPONSE, SUNWEG_PLANT_RESPONSE from .common import SUNWEG_USER_INPUT
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@ -32,7 +31,7 @@ async def test_incorrect_login(hass: HomeAssistant) -> None:
with patch.object(APIHelper, "authenticate", return_value=False): with patch.object(APIHelper, "authenticate", return_value=False):
result = await hass.config_entries.flow.async_configure( result = await hass.config_entries.flow.async_configure(
result["flow_id"], FIXTURE_USER_INPUT result["flow_id"], SUNWEG_USER_INPUT
) )
assert result["type"] == data_entry_flow.FlowResultType.FORM assert result["type"] == data_entry_flow.FlowResultType.FORM
@ -41,34 +40,33 @@ async def test_incorrect_login(hass: HomeAssistant) -> None:
async def test_no_plants_on_account(hass: HomeAssistant) -> None: async def test_no_plants_on_account(hass: HomeAssistant) -> None:
"""Test registering an integration and finishing flow with an entered plant_id.""" """Test registering an integration with no plants available."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
user_input = FIXTURE_USER_INPUT.copy()
with patch.object( with patch.object(APIHelper, "authenticate", return_value=True), patch.object(
APIHelper, "authenticate", return_value=SUNWEG_LOGIN_RESPONSE APIHelper, "listPlants", return_value=[]
), patch.object(APIHelper, "listPlants", return_value=[]): ):
result = await hass.config_entries.flow.async_configure( result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input result["flow_id"], SUNWEG_USER_INPUT
) )
assert result["type"] == "abort" assert result["type"] == "abort"
assert result["reason"] == "no_plants" assert result["reason"] == "no_plants"
async def test_multiple_plant_ids(hass: HomeAssistant) -> None: async def test_multiple_plant_ids(hass: HomeAssistant, plant_fixture) -> None:
"""Test registering an integration and finishing flow with an entered plant_id.""" """Test registering an integration and finishing flow with an selected plant_id."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
user_input = FIXTURE_USER_INPUT.copy() user_input = SUNWEG_USER_INPUT.copy()
plant_list = [deepcopy(SUNWEG_PLANT_RESPONSE), deepcopy(SUNWEG_PLANT_RESPONSE)] plant_list = [plant_fixture, plant_fixture]
with patch.object( with patch.object(APIHelper, "authenticate", return_value=True), patch.object(
APIHelper, "authenticate", return_value=SUNWEG_LOGIN_RESPONSE APIHelper, "listPlants", return_value=plant_list
), patch.object(APIHelper, "listPlants", return_value=plant_list): ):
result = await hass.config_entries.flow.async_configure( result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input result["flow_id"], user_input
) )
@ -82,50 +80,46 @@ async def test_multiple_plant_ids(hass: HomeAssistant) -> None:
await hass.async_block_till_done() await hass.async_block_till_done()
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
assert result["data"][CONF_USERNAME] == FIXTURE_USER_INPUT[CONF_USERNAME] assert result["data"][CONF_USERNAME] == SUNWEG_USER_INPUT[CONF_USERNAME]
assert result["data"][CONF_PASSWORD] == FIXTURE_USER_INPUT[CONF_PASSWORD] assert result["data"][CONF_PASSWORD] == SUNWEG_USER_INPUT[CONF_PASSWORD]
assert result["data"][CONF_PLANT_ID] == 123456 assert result["data"][CONF_PLANT_ID] == 123456
async def test_one_plant_on_account(hass: HomeAssistant) -> None: async def test_one_plant_on_account(hass: HomeAssistant, plant_fixture) -> None:
"""Test registering an integration and finishing flow with an entered plant_id.""" """Test registering an integration and finishing flow with current plant_id."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
user_input = FIXTURE_USER_INPUT.copy() user_input = SUNWEG_USER_INPUT.copy()
with patch.object( with patch.object(APIHelper, "authenticate", return_value=True), patch.object(
APIHelper, "authenticate", return_value=SUNWEG_LOGIN_RESPONSE
), patch.object(
APIHelper, APIHelper,
"listPlants", "listPlants",
return_value=[deepcopy(SUNWEG_PLANT_RESPONSE)], return_value=[plant_fixture],
): ):
result = await hass.config_entries.flow.async_configure( result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input result["flow_id"], user_input
) )
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
assert result["data"][CONF_USERNAME] == FIXTURE_USER_INPUT[CONF_USERNAME] assert result["data"][CONF_USERNAME] == SUNWEG_USER_INPUT[CONF_USERNAME]
assert result["data"][CONF_PASSWORD] == FIXTURE_USER_INPUT[CONF_PASSWORD] assert result["data"][CONF_PASSWORD] == SUNWEG_USER_INPUT[CONF_PASSWORD]
assert result["data"][CONF_PLANT_ID] == 123456 assert result["data"][CONF_PLANT_ID] == 123456
async def test_existing_plant_configured(hass: HomeAssistant) -> None: async def test_existing_plant_configured(hass: HomeAssistant, plant_fixture) -> None:
"""Test entering an existing plant_id.""" """Test entering an existing plant_id."""
entry = MockConfigEntry(domain=DOMAIN, unique_id=123456) entry = MockConfigEntry(domain=DOMAIN, unique_id=123456)
entry.add_to_hass(hass) entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
user_input = FIXTURE_USER_INPUT.copy() user_input = SUNWEG_USER_INPUT.copy()
with patch.object( with patch.object(APIHelper, "authenticate", return_value=True), patch.object(
APIHelper, "authenticate", return_value=SUNWEG_LOGIN_RESPONSE
), patch.object(
APIHelper, APIHelper,
"listPlants", "listPlants",
return_value=[deepcopy(SUNWEG_PLANT_RESPONSE)], return_value=[plant_fixture],
): ):
result = await hass.config_entries.flow.async_configure( result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input result["flow_id"], user_input

View File

@ -1,51 +1,31 @@
"""Tests for the Sun WEG init.""" """Tests for the Sun WEG init."""
from copy import deepcopy
import json import json
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from sunweg.api import APIHelper from sunweg.api import APIHelper, SunWegApiError
from sunweg.device import MPPT, Inverter
from sunweg.plant import Plant
from homeassistant.components.sunweg import SunWEGData from homeassistant.components.sunweg import SunWEGData
from homeassistant.components.sunweg.const import DOMAIN from homeassistant.components.sunweg.const import DOMAIN, DeviceType
from homeassistant.components.sunweg.sensor_types.sensor_entity_description import ( from homeassistant.components.sunweg.sensor_types.sensor_entity_description import (
SunWEGSensorEntityDescription, SunWEGSensorEntityDescription,
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from .common import ( from .common import SUNWEG_MOCK_ENTRY
SUNWEG_INVERTER_RESPONSE,
SUNWEG_LOGIN_RESPONSE,
SUNWEG_MOCK_ENTRY,
SUNWEG_MPPT_RESPONSE,
SUNWEG_PHASE_RESPONSE,
SUNWEG_PLANT_RESPONSE,
SUNWEG_STRING_RESPONSE,
)
async def test_methods(hass: HomeAssistant) -> None: async def test_methods(hass: HomeAssistant, plant_fixture, inverter_fixture) -> None:
"""Test methods.""" """Test methods."""
mock_entry = SUNWEG_MOCK_ENTRY mock_entry = SUNWEG_MOCK_ENTRY
mock_entry.add_to_hass(hass) mock_entry.add_to_hass(hass)
mppt: MPPT = deepcopy(SUNWEG_MPPT_RESPONSE)
mppt.strings.append(SUNWEG_STRING_RESPONSE)
inverter: Inverter = deepcopy(SUNWEG_INVERTER_RESPONSE)
inverter.phases.append(SUNWEG_PHASE_RESPONSE)
inverter.mppts.append(mppt)
plant: Plant = deepcopy(SUNWEG_PLANT_RESPONSE)
plant.inverters.append(inverter)
with patch.object( with patch.object(APIHelper, "authenticate", return_value=True), patch.object(
APIHelper, "authenticate", return_value=SUNWEG_LOGIN_RESPONSE APIHelper, "listPlants", return_value=[plant_fixture]
), patch.object(APIHelper, "listPlants", return_value=[plant]), patch.object( ), patch.object(APIHelper, "plant", return_value=plant_fixture), patch.object(
APIHelper, "plant", return_value=plant APIHelper, "inverter", return_value=inverter_fixture
), patch.object(APIHelper, "inverter", return_value=inverter), patch.object( ), patch.object(APIHelper, "complete_inverter"):
APIHelper, "complete_inverter"
):
assert await async_setup_component(hass, DOMAIN, mock_entry.data) assert await async_setup_component(hass, DOMAIN, mock_entry.data)
await hass.async_block_till_done() await hass.async_block_till_done()
assert await hass.config_entries.async_unload(mock_entry.entry_id) assert await hass.config_entries.async_unload(mock_entry.entry_id)
@ -60,6 +40,17 @@ async def test_setup_wrongpass(hass: HomeAssistant) -> None:
await hass.async_block_till_done() await hass.async_block_till_done()
async def test_setup_error_500(hass: HomeAssistant) -> None:
"""Test setup with wrong pass."""
mock_entry = SUNWEG_MOCK_ENTRY
mock_entry.add_to_hass(hass)
with patch.object(
APIHelper, "authenticate", side_effect=SunWegApiError("Error 500")
):
assert await async_setup_component(hass, DOMAIN, mock_entry.data)
await hass.async_block_till_done()
async def test_sunwegdata_update_exception() -> None: async def test_sunwegdata_update_exception() -> None:
"""Test SunWEGData exception on update.""" """Test SunWEGData exception on update."""
api = MagicMock() api = MagicMock()
@ -69,33 +60,29 @@ async def test_sunwegdata_update_exception() -> None:
assert data.data is None assert data.data is None
async def test_sunwegdata_update_success() -> None: async def test_sunwegdata_update_success(plant_fixture) -> None:
"""Test SunWEGData success on update.""" """Test SunWEGData success on update."""
inverter: Inverter = deepcopy(SUNWEG_INVERTER_RESPONSE)
plant: Plant = deepcopy(SUNWEG_PLANT_RESPONSE)
plant.inverters.append(inverter)
api = MagicMock() api = MagicMock()
api.plant = MagicMock(return_value=plant) api.plant = MagicMock(return_value=plant_fixture)
api.complete_inverter = MagicMock() api.complete_inverter = MagicMock()
data = SunWEGData(api, 0) data = SunWEGData(api, 0)
data.update() data.update()
assert data.data.id == plant.id assert data.data.id == plant_fixture.id
assert data.data.name == plant.name assert data.data.name == plant_fixture.name
assert data.data.kwh_per_kwp == plant.kwh_per_kwp assert data.data.kwh_per_kwp == plant_fixture.kwh_per_kwp
assert data.data.last_update == plant.last_update assert data.data.last_update == plant_fixture.last_update
assert data.data.performance_rate == plant.performance_rate assert data.data.performance_rate == plant_fixture.performance_rate
assert data.data.saving == plant.saving assert data.data.saving == plant_fixture.saving
assert len(data.data.inverters) == 1 assert len(data.data.inverters) == 1
async def test_sunwegdata_get_api_value_none() -> None: async def test_sunwegdata_get_api_value_none(plant_fixture) -> None:
"""Test SunWEGData none return on get_api_value.""" """Test SunWEGData none return on get_api_value."""
api = MagicMock() api = MagicMock()
data = SunWEGData(api, 123456) data = SunWEGData(api, 123456)
data.data = deepcopy(SUNWEG_PLANT_RESPONSE) data.data = plant_fixture
assert data.get_api_value("variable", "inverter", 0, "deep_name") is None assert data.get_api_value("variable", DeviceType.INVERTER, 0, "deep_name") is None
data.data.inverters.append(deepcopy(SUNWEG_INVERTER_RESPONSE)) assert data.get_api_value("variable", DeviceType.STRING, 21255, "deep_name") is None
assert data.get_api_value("variable", "invalid type", 21255, "deep_name") is None
async def test_sunwegdata_get_data_drop_threshold() -> None: async def test_sunwegdata_get_data_drop_threshold() -> None:
@ -109,15 +96,24 @@ async def test_sunwegdata_get_data_drop_threshold() -> None:
entity_description.previous_value_drop_threshold = 0.1 entity_description.previous_value_drop_threshold = 0.1
data.get_api_value.return_value = 3.0 data.get_api_value.return_value = 3.0
assert ( assert (
data.get_data(entity_description=entity_description, device_type="total") == 3.0 data.get_data(
entity_description=entity_description, device_type=DeviceType.TOTAL
)
== 3.0
) )
data.get_api_value.return_value = 2.91 data.get_api_value.return_value = 2.91
assert ( assert (
data.get_data(entity_description=entity_description, device_type="total") == 3.0 data.get_data(
entity_description=entity_description, device_type=DeviceType.TOTAL
)
== 3.0
) )
data.get_api_value.return_value = 2.8 data.get_api_value.return_value = 2.8
assert ( assert (
data.get_data(entity_description=entity_description, device_type="total") == 2.8 data.get_data(
entity_description=entity_description, device_type=DeviceType.TOTAL
)
== 2.8
) )
@ -132,13 +128,22 @@ async def test_sunwegdata_get_data_never_reset() -> None:
entity_description.never_resets = True entity_description.never_resets = True
data.get_api_value.return_value = 3.0 data.get_api_value.return_value = 3.0
assert ( assert (
data.get_data(entity_description=entity_description, device_type="total") == 3.0 data.get_data(
entity_description=entity_description, device_type=DeviceType.TOTAL
)
== 3.0
) )
data.get_api_value.return_value = 0 data.get_api_value.return_value = 0
assert ( assert (
data.get_data(entity_description=entity_description, device_type="total") == 3.0 data.get_data(
entity_description=entity_description, device_type=DeviceType.TOTAL
)
== 3.0
) )
data.get_api_value.return_value = 2.8 data.get_api_value.return_value = 2.8
assert ( assert (
data.get_data(entity_description=entity_description, device_type="total") == 2.8 data.get_data(
entity_description=entity_description, device_type=DeviceType.TOTAL
)
== 2.8
) )