Add fixture files to Enphase_Envoy tests (#121864)

* Add fixture files to Enphase_Envoy tests

* optimize fixtures in enphase_envoy conftest

* combine setup_enphase_envoy and mock_envoy in enphase_envoy tests

* Revert "combine setup_enphase_envoy and mock_envoy in enphase_envoy tests"

This reverts commit ec072c4726bc1348f87608f744ff06117e762bae.

* Rework enphase tests

* Rework enphase tests

* reset diagnostics test snapshot

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
Arie Catsman 2024-07-16 21:14:46 +02:00 committed by GitHub
parent a22e12dac9
commit baa97ca981
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 13180 additions and 15340 deletions

View File

@ -1 +1,13 @@
"""Tests for the Enphase Envoy integration.""" """Tests for the Enphase Envoy 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)
await hass.async_block_till_done()

View File

@ -1,50 +1,56 @@
"""Define test fixtures for Enphase Envoy.""" """Define test fixtures for Enphase Envoy."""
from collections.abc import AsyncGenerator from collections.abc import AsyncGenerator, Generator
from typing import Any
from unittest.mock import AsyncMock, Mock, patch from unittest.mock import AsyncMock, Mock, patch
import jwt import jwt
from pyenphase import ( from pyenphase import (
Envoy,
EnvoyData, EnvoyData,
EnvoyEncharge,
EnvoyEnchargeAggregate,
EnvoyEnchargePower,
EnvoyEnpower,
EnvoyInverter, EnvoyInverter,
EnvoySystemConsumption, EnvoySystemConsumption,
EnvoySystemProduction, EnvoySystemProduction,
EnvoyTokenAuth, EnvoyTokenAuth,
) )
from pyenphase.const import PhaseNames, SupportedFeatures from pyenphase.const import SupportedFeatures
from pyenphase.models.meters import ( from pyenphase.models.dry_contacts import EnvoyDryContactSettings, EnvoyDryContactStatus
CtMeterStatus, from pyenphase.models.meters import EnvoyMeterData
CtState, from pyenphase.models.tariff import EnvoyStorageSettings, EnvoyTariff
CtStatusFlags,
CtType,
EnvoyMeterData,
EnvoyPhaseMode,
)
import pytest import pytest
from homeassistant.components.enphase_envoy import DOMAIN from homeassistant.components.enphase_envoy import DOMAIN
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_USERNAME from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry from tests.common import MockConfigEntry, load_json_object_fixture
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.enphase_envoy.async_setup_entry",
return_value=True,
) as mock_setup_entry:
yield mock_setup_entry
@pytest.fixture(name="config_entry") @pytest.fixture(name="config_entry")
def config_entry_fixture( def config_entry_fixture(
hass: HomeAssistant, config: dict[str, str], serial_number: str hass: HomeAssistant, config: dict[str, str]
) -> MockConfigEntry: ) -> MockConfigEntry:
"""Define a config entry fixture.""" """Define a config entry fixture."""
entry = MockConfigEntry( return MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,
entry_id="45a36e55aaddb2007c5f6602e0c38e72", entry_id="45a36e55aaddb2007c5f6602e0c38e72",
title=f"Envoy {serial_number}" if serial_number else "Envoy", title="Envoy 1234",
unique_id=serial_number, unique_id="1234",
data=config, data=config,
) )
entry.add_to_hass(hass)
return entry
@pytest.fixture(name="config") @pytest.fixture(name="config")
@ -58,344 +64,173 @@ def config_fixture() -> dict[str, str]:
} }
@pytest.fixture(name="mock_envoy") @pytest.fixture
def mock_envoy_fixture( async def mock_envoy(
serial_number: str, request: pytest.FixtureRequest,
mock_authenticate: AsyncMock, ) -> AsyncGenerator[AsyncMock, None]:
mock_setup: AsyncMock,
mock_auth: EnvoyTokenAuth,
) -> Mock:
"""Define a mocked Envoy fixture.""" """Define a mocked Envoy fixture."""
mock_envoy = Mock(spec=Envoy)
mock_envoy.serial_number = serial_number
mock_envoy.firmware = "7.1.2"
mock_envoy.part_number = "123456789"
mock_envoy.envoy_model = "Envoy, phases: 3, phase mode: three, net-consumption CT, production CT, storage CT"
mock_envoy.authenticate = mock_authenticate
mock_envoy.setup = mock_setup
mock_envoy.auth = mock_auth
mock_envoy.supported_features = SupportedFeatures(
SupportedFeatures.INVERTERS
| SupportedFeatures.PRODUCTION
| SupportedFeatures.PRODUCTION
| SupportedFeatures.METERING
| SupportedFeatures.THREEPHASE
| SupportedFeatures.CTMETERS
)
mock_envoy.phase_mode = EnvoyPhaseMode.THREE
mock_envoy.phase_count = 3
mock_envoy.active_phase_count = 3
mock_envoy.ct_meter_count = 3
mock_envoy.consumption_meter_type = CtType.NET_CONSUMPTION
mock_envoy.production_meter_type = CtType.PRODUCTION
mock_envoy.storage_meter_type = CtType.STORAGE
mock_envoy.data = EnvoyData(
system_consumption=EnvoySystemConsumption(
watt_hours_last_7_days=1234,
watt_hours_lifetime=1234,
watt_hours_today=1234,
watts_now=1234,
),
system_production=EnvoySystemProduction(
watt_hours_last_7_days=1234,
watt_hours_lifetime=1234,
watt_hours_today=1234,
watts_now=1234,
),
system_consumption_phases={
PhaseNames.PHASE_1: EnvoySystemConsumption(
watt_hours_last_7_days=1321,
watt_hours_lifetime=1322,
watt_hours_today=1323,
watts_now=1324,
),
PhaseNames.PHASE_2: EnvoySystemConsumption(
watt_hours_last_7_days=2321,
watt_hours_lifetime=2322,
watt_hours_today=2323,
watts_now=2324,
),
PhaseNames.PHASE_3: EnvoySystemConsumption(
watt_hours_last_7_days=3321,
watt_hours_lifetime=3322,
watt_hours_today=3323,
watts_now=3324,
),
},
system_production_phases={
PhaseNames.PHASE_1: EnvoySystemProduction(
watt_hours_last_7_days=1231,
watt_hours_lifetime=1232,
watt_hours_today=1233,
watts_now=1234,
),
PhaseNames.PHASE_2: EnvoySystemProduction(
watt_hours_last_7_days=2231,
watt_hours_lifetime=2232,
watt_hours_today=2233,
watts_now=2234,
),
PhaseNames.PHASE_3: EnvoySystemProduction(
watt_hours_last_7_days=3231,
watt_hours_lifetime=3232,
watt_hours_today=3233,
watts_now=3234,
),
},
ctmeter_production=EnvoyMeterData(
eid="100000010",
timestamp=1708006110,
energy_delivered=11234,
energy_received=12345,
active_power=100,
power_factor=0.11,
voltage=111,
current=0.2,
frequency=50.1,
state=CtState.ENABLED,
measurement_type=CtType.PRODUCTION,
metering_status=CtMeterStatus.NORMAL,
status_flags=[
CtStatusFlags.PODUCTION_IMBALANCE,
CtStatusFlags.POWER_ON_UNUSED_PHASE,
],
),
ctmeter_consumption=EnvoyMeterData(
eid="100000020",
timestamp=1708006120,
energy_delivered=21234,
energy_received=22345,
active_power=101,
power_factor=0.21,
voltage=112,
current=0.3,
frequency=50.2,
state=CtState.ENABLED,
measurement_type=CtType.NET_CONSUMPTION,
metering_status=CtMeterStatus.NORMAL,
status_flags=[],
),
ctmeter_storage=EnvoyMeterData(
eid="100000030",
timestamp=1708006120,
energy_delivered=31234,
energy_received=32345,
active_power=103,
power_factor=0.23,
voltage=113,
current=0.4,
frequency=50.3,
state=CtState.ENABLED,
measurement_type=CtType.STORAGE,
metering_status=CtMeterStatus.NORMAL,
status_flags=[],
),
ctmeter_production_phases={
PhaseNames.PHASE_1: EnvoyMeterData(
eid="100000011",
timestamp=1708006111,
energy_delivered=112341,
energy_received=123451,
active_power=20,
power_factor=0.12,
voltage=111,
current=0.2,
frequency=50.1,
state=CtState.ENABLED,
measurement_type=CtType.PRODUCTION,
metering_status=CtMeterStatus.NORMAL,
status_flags=[CtStatusFlags.PODUCTION_IMBALANCE],
),
PhaseNames.PHASE_2: EnvoyMeterData(
eid="100000012",
timestamp=1708006112,
energy_delivered=112342,
energy_received=123452,
active_power=30,
power_factor=0.13,
voltage=111,
current=0.2,
frequency=50.1,
state=CtState.ENABLED,
measurement_type=CtType.PRODUCTION,
metering_status=CtMeterStatus.NORMAL,
status_flags=[CtStatusFlags.POWER_ON_UNUSED_PHASE],
),
PhaseNames.PHASE_3: EnvoyMeterData(
eid="100000013",
timestamp=1708006113,
energy_delivered=112343,
energy_received=123453,
active_power=50,
power_factor=0.14,
voltage=111,
current=0.2,
frequency=50.1,
state=CtState.ENABLED,
measurement_type=CtType.PRODUCTION,
metering_status=CtMeterStatus.NORMAL,
status_flags=[],
),
},
ctmeter_consumption_phases={
PhaseNames.PHASE_1: EnvoyMeterData(
eid="100000021",
timestamp=1708006121,
energy_delivered=212341,
energy_received=223451,
active_power=21,
power_factor=0.22,
voltage=112,
current=0.3,
frequency=50.2,
state=CtState.ENABLED,
measurement_type=CtType.NET_CONSUMPTION,
metering_status=CtMeterStatus.NORMAL,
status_flags=[],
),
PhaseNames.PHASE_2: EnvoyMeterData(
eid="100000022",
timestamp=1708006122,
energy_delivered=212342,
energy_received=223452,
active_power=31,
power_factor=0.23,
voltage=112,
current=0.3,
frequency=50.2,
state=CtState.ENABLED,
measurement_type=CtType.NET_CONSUMPTION,
metering_status=CtMeterStatus.NORMAL,
status_flags=[],
),
PhaseNames.PHASE_3: EnvoyMeterData(
eid="100000023",
timestamp=1708006123,
energy_delivered=212343,
energy_received=223453,
active_power=51,
power_factor=0.24,
voltage=112,
current=0.3,
frequency=50.2,
state=CtState.ENABLED,
measurement_type=CtType.NET_CONSUMPTION,
metering_status=CtMeterStatus.NORMAL,
status_flags=[],
),
},
ctmeter_storage_phases={
PhaseNames.PHASE_1: EnvoyMeterData(
eid="100000031",
timestamp=1708006121,
energy_delivered=312341,
energy_received=323451,
active_power=22,
power_factor=0.32,
voltage=113,
current=0.4,
frequency=50.3,
state=CtState.ENABLED,
measurement_type=CtType.STORAGE,
metering_status=CtMeterStatus.NORMAL,
status_flags=[],
),
PhaseNames.PHASE_2: EnvoyMeterData(
eid="100000032",
timestamp=1708006122,
energy_delivered=312342,
energy_received=323452,
active_power=33,
power_factor=0.23,
voltage=112,
current=0.3,
frequency=50.2,
state=CtState.ENABLED,
measurement_type=CtType.STORAGE,
metering_status=CtMeterStatus.NORMAL,
status_flags=[],
),
PhaseNames.PHASE_3: EnvoyMeterData(
eid="100000033",
timestamp=1708006123,
energy_delivered=312343,
energy_received=323453,
active_power=53,
power_factor=0.24,
voltage=112,
current=0.3,
frequency=50.2,
state=CtState.ENABLED,
measurement_type=CtType.STORAGE,
metering_status=CtMeterStatus.NORMAL,
status_flags=[],
),
},
inverters={
"1": EnvoyInverter(
serial_number="1",
last_report_date=1,
last_report_watts=1,
max_report_watts=1,
)
},
raw={"varies_by": "firmware_version"},
)
mock_envoy.update = AsyncMock(return_value=mock_envoy.data)
response = Mock()
response.status_code = 200
response.text = "Testing request \nreplies."
response.headers = {"Hello": "World"}
mock_envoy.request = AsyncMock(return_value=response)
return mock_envoy
@pytest.fixture(name="setup_enphase_envoy")
async def setup_enphase_envoy_fixture(
hass: HomeAssistant,
config: dict[str, str],
mock_envoy: Mock,
) -> AsyncGenerator[None]:
"""Define a fixture to set up Enphase Envoy."""
with ( with (
patch( patch(
"homeassistant.components.enphase_envoy.config_flow.Envoy", "homeassistant.components.enphase_envoy.config_flow.Envoy",
return_value=mock_envoy, autospec=True,
), ) as mock_client,
patch( patch(
"homeassistant.components.enphase_envoy.Envoy", "homeassistant.components.enphase_envoy.Envoy",
return_value=mock_envoy, new=mock_client,
), ),
): ):
assert await async_setup_component(hass, DOMAIN, config) mock_envoy = mock_client.return_value
await hass.async_block_till_done() # Add the fixtures specified
yield
@pytest.fixture(name="mock_authenticate")
def mock_authenticate() -> AsyncMock:
"""Define a mocked Envoy.authenticate fixture."""
return AsyncMock()
@pytest.fixture(name="mock_auth")
def mock_auth(serial_number: str) -> EnvoyTokenAuth:
"""Define a mocked EnvoyAuth fixture."""
token = jwt.encode( token = jwt.encode(
payload={"name": "envoy", "exp": 1907837780}, key="secret", algorithm="HS256" payload={"name": "envoy", "exp": 1907837780},
key="secret",
algorithm="HS256",
) )
return EnvoyTokenAuth("127.0.0.1", token=token, envoy_serial=serial_number) mock_envoy.auth = EnvoyTokenAuth("127.0.0.1", token=token, envoy_serial="1234")
mock_envoy.serial_number = "1234"
mock = Mock()
mock.status_code = 200
mock.text = "Testing request \nreplies."
mock.headers = {"Hello": "World"}
mock_envoy.request.return_value = mock
# determine fixture file name, default envoy if no request passed
fixture_name = "envoy"
if hasattr(request, "param"):
fixture_name = request.param
# Load envoy model from fixture
load_envoy_fixture(mock_envoy, fixture_name)
mock_envoy.update.return_value = mock_envoy.data
yield mock_envoy
@pytest.fixture(name="mock_setup") def load_envoy_fixture(mock_envoy: AsyncMock, fixture_name: str) -> None:
def mock_setup() -> AsyncMock: """Load envoy model from fixture."""
"""Define a mocked Envoy.setup fixture."""
return AsyncMock() json_fixture: dict[str, Any] = load_json_object_fixture(
f"{fixture_name}.json", DOMAIN
)
mock_envoy.firmware = json_fixture["firmware"]
mock_envoy.part_number = json_fixture["part_number"]
mock_envoy.envoy_model = json_fixture["envoy_model"]
mock_envoy.supported_features = SupportedFeatures(
json_fixture["supported_features"]
)
mock_envoy.phase_mode = json_fixture["phase_mode"]
mock_envoy.phase_count = json_fixture["phase_count"]
mock_envoy.active_phase_count = json_fixture["active_phase_count"]
mock_envoy.ct_meter_count = json_fixture["ct_meter_count"]
mock_envoy.consumption_meter_type = json_fixture["consumption_meter_type"]
mock_envoy.production_meter_type = json_fixture["production_meter_type"]
mock_envoy.storage_meter_type = json_fixture["storage_meter_type"]
mock_envoy.data = EnvoyData()
_load_json_2_production_data(mock_envoy.data, json_fixture)
_load_json_2_meter_data(mock_envoy.data, json_fixture)
_load_json_2_inverter_data(mock_envoy.data, json_fixture)
_load_json_2_encharge_enpower_data(mock_envoy.data, json_fixture)
_load_json_2_raw_data(mock_envoy.data, json_fixture)
@pytest.fixture(name="serial_number") def _load_json_2_production_data(
def serial_number_fixture() -> str: mocked_data: EnvoyData, json_fixture: dict[str, Any]
"""Define a serial number fixture.""" ) -> None:
return "1234" """Fill envoy production data from fixture."""
if item := json_fixture["data"].get("system_consumption"):
mocked_data.system_consumption = EnvoySystemConsumption(**item)
if item := json_fixture["data"].get("system_production"):
mocked_data.system_production = EnvoySystemProduction(**item)
if item := json_fixture["data"].get("system_consumption_phases"):
mocked_data.system_consumption_phases = {}
for sub_item, item_data in item.items():
mocked_data.system_consumption_phases[sub_item] = EnvoySystemConsumption(
**item_data
)
if item := json_fixture["data"].get("system_production_phases"):
mocked_data.system_production_phases = {}
for sub_item, item_data in item.items():
mocked_data.system_production_phases[sub_item] = EnvoySystemProduction(
**item_data
)
def _load_json_2_meter_data(
mocked_data: EnvoyData, json_fixture: dict[str, Any]
) -> None:
"""Fill envoy meter data from fixture."""
if item := json_fixture["data"].get("ctmeter_production"):
mocked_data.ctmeter_production = EnvoyMeterData(**item)
if item := json_fixture["data"].get("ctmeter_consumption"):
mocked_data.ctmeter_consumption = EnvoyMeterData(**item)
if item := json_fixture["data"].get("ctmeter_storage"):
mocked_data.ctmeter_storage = EnvoyMeterData(**item)
if item := json_fixture["data"].get("ctmeter_production_phases"):
mocked_data.ctmeter_production_phases = {}
for sub_item, item_data in item.items():
mocked_data.ctmeter_production_phases[sub_item] = EnvoyMeterData(
**item_data
)
if item := json_fixture["data"].get("ctmeter_consumption_phases"):
mocked_data.ctmeter_consumption_phases = {}
for sub_item, item_data in item.items():
mocked_data.ctmeter_consumption_phases[sub_item] = EnvoyMeterData(
**item_data
)
if item := json_fixture["data"].get("ctmeter_storage_phases"):
mocked_data.ctmeter_storage_phases = {}
for sub_item, item_data in item.items():
mocked_data.ctmeter_storage_phases[sub_item] = EnvoyMeterData(**item_data)
def _load_json_2_inverter_data(
mocked_data: EnvoyData, json_fixture: dict[str, Any]
) -> None:
"""Fill envoy inverter data from fixture."""
if item := json_fixture["data"].get("inverters"):
mocked_data.inverters = {}
for sub_item, item_data in item.items():
mocked_data.inverters[sub_item] = EnvoyInverter(**item_data)
def _load_json_2_encharge_enpower_data(
mocked_data: EnvoyData, json_fixture: dict[str, Any]
) -> None:
"""Fill envoy encharge/enpower data from fixture."""
if item := json_fixture["data"].get("encharge_inventory"):
mocked_data.encharge_inventory = {}
for sub_item, item_data in item.items():
mocked_data.encharge_inventory[sub_item] = EnvoyEncharge(**item_data)
if item := json_fixture["data"].get("enpower"):
mocked_data.enpower = EnvoyEnpower(**item)
if item := json_fixture["data"].get("encharge_aggregate"):
mocked_data.encharge_aggregate = EnvoyEnchargeAggregate(**item)
if item := json_fixture["data"].get("encharge_power"):
mocked_data.encharge_power = {}
for sub_item, item_data in item.items():
mocked_data.encharge_power[sub_item] = EnvoyEnchargePower(**item_data)
if item := json_fixture["data"].get("tariff"):
mocked_data.tariff = EnvoyTariff(**item)
mocked_data.tariff.storage_settings = EnvoyStorageSettings(
**item["storage_settings"]
)
if item := json_fixture["data"].get("dry_contact_status"):
mocked_data.dry_contact_status = {}
for sub_item, item_data in item.items():
mocked_data.dry_contact_status[sub_item] = EnvoyDryContactStatus(
**item_data
)
if item := json_fixture["data"].get("dry_contact_settings"):
mocked_data.dry_contact_settings = {}
for sub_item, item_data in item.items():
mocked_data.dry_contact_settings[sub_item] = EnvoyDryContactSettings(
**item_data
)
def _load_json_2_raw_data(mocked_data: EnvoyData, json_fixture: dict[str, Any]) -> None:
"""Fill envoy raw data from fixture."""
if item := json_fixture["data"].get("raw"):
mocked_data.raw = item

View File

@ -0,0 +1,49 @@
{
"serial_number": "1234",
"firmware": "7.6.175",
"part_number": "123456789",
"envoy_model": "Envoy",
"supported_features": 65,
"phase_mode": null,
"phase_count": 1,
"active_phase_count": 0,
"ct_meter_count": 0,
"consumption_meter_type": null,
"production_meter_type": null,
"storage_meter_type": null,
"data": {
"encharge_inventory": null,
"encharge_power": null,
"encharge_aggregate": null,
"enpower": null,
"system_consumption": null,
"system_production": {
"watt_hours_lifetime": 1234,
"watt_hours_last_7_days": 1234,
"watt_hours_today": 1234,
"watts_now": 1234
},
"system_consumption_phases": null,
"system_production_phases": null,
"ctmeter_production": null,
"ctmeter_consumption": null,
"ctmeter_storage": null,
"ctmeter_production_phases": null,
"ctmeter_consumption_phases": null,
"ctmeter_storage_phases": null,
"dry_contact_status": {},
"dry_contact_settings": {},
"inverters": {
"1": {
"serial_number": "1",
"last_report_date": 1,
"last_report_watts": 1,
"max_report_watts": 1
}
},
"tariff": null,
"raw": {
"varies_by": "firmware_version"
}
}
}

View File

@ -0,0 +1,130 @@
{
"serial_number": "1234",
"firmware": "7.6.175",
"part_number": "123456789",
"envoy_model": "Envoy, phases: 1, phase mode: three, net-consumption CT, production CT",
"supported_features": 1231,
"phase_mode": "three",
"phase_count": 1,
"active_phase_count": 0,
"ct_meter_count": 2,
"consumption_meter_type": "net-consumption",
"production_meter_type": "production",
"storage_meter_type": null,
"data": {
"encharge_inventory": null,
"encharge_power": null,
"encharge_aggregate": null,
"enpower": null,
"system_consumption": {
"watt_hours_lifetime": 1234,
"watt_hours_last_7_days": 1234,
"watt_hours_today": 1234,
"watts_now": 1234
},
"system_production": {
"watt_hours_lifetime": 1234,
"watt_hours_last_7_days": 1234,
"watt_hours_today": 1234,
"watts_now": 1234
},
"system_consumption_phases": null,
"system_production_phases": null,
"ctmeter_production": {
"eid": "100000010",
"timestamp": 1708006110,
"energy_delivered": 11234,
"energy_received": 12345,
"active_power": 100,
"power_factor": 0.11,
"voltage": 111,
"current": 0.2,
"frequency": 50.1,
"state": "enabled",
"measurement_type": "production",
"metering_status": "normal",
"status_flags": ["production-imbalance", "power-on-unused-phase"]
},
"ctmeter_consumption": {
"eid": "100000020",
"timestamp": 1708006120,
"energy_delivered": 21234,
"energy_received": 22345,
"active_power": 101,
"power_factor": 0.21,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "net-consumption",
"metering_status": "normal",
"status_flags": []
},
"ctmeter_storage": null,
"ctmeter_production_phases": null,
"ctmeter_consumption_phases": null,
"ctmeter_storage_phases": null,
"dry_contact_status": {},
"dry_contact_settings": {},
"inverters": {
"1": {
"serial_number": "1",
"last_report_date": 1,
"last_report_watts": 1,
"max_report_watts": 1
}
},
"tariff": {
"currency": {
"code": "EUR"
},
"logger": "mylogger",
"date": "1695744220",
"storage_settings": {
"mode": "self-consumption",
"operation_mode_sub_type": "",
"reserved_soc": 15.0,
"very_low_soc": 5,
"charge_from_grid": true,
"date": "1695598084"
},
"single_rate": {
"rate": 0.0,
"sell": 0.0
},
"seasons": [
{
"id": "season_1",
"start": "1/1",
"days": [
{
"id": "all_days",
"days": "Mon,Tue,Wed,Thu,Fri,Sat,Sun",
"must_charge_start": 444,
"must_charge_duration": 35,
"must_charge_mode": "CG",
"enable_discharge_to_grid": true,
"periods": [
{
"id": "period_1",
"start": 480,
"rate": 0.1898
},
{
"id": "filler",
"start": 1320,
"rate": 0.1034
}
]
}
],
"tiers": []
}
],
"seasons_sell": []
},
"raw": {
"varies_by": "firmware_version"
}
}
}

View File

@ -0,0 +1,445 @@
{
"serial_number": "1234",
"firmware": "7.1.2",
"part_number": "123456789",
"envoy_model": "Envoy, phases: 3, phase mode: split, net-consumption CT, production CT, storage CT",
"supported_features": 1659,
"phase_mode": "three",
"phase_count": 3,
"active_phase_count": 3,
"ct_meter_count": 2,
"consumption_meter_type": "net-consumption",
"production_meter_type": "production",
"storage_meter_type": "storage",
"data": {
"encharge_inventory": {
"123456": {
"admin_state": 6,
"admin_state_str": "ENCHG_STATE_READY",
"bmu_firmware_version": "2.1.34",
"comm_level_2_4_ghz": 4,
"comm_level_sub_ghz": 4,
"communicating": true,
"dc_switch_off": false,
"encharge_capacity": 3500,
"encharge_revision": 2,
"firmware_loaded_date": 1695330323,
"firmware_version": "2.6.5973_rel/22.11",
"installed_date": 1695330323,
"last_report_date": 1695769447,
"led_status": 17,
"max_cell_temp": 30,
"operating": true,
"part_number": "830-01760-r37",
"percent_full": 15,
"serial_number": "123456",
"temperature": 29,
"temperature_unit": "C",
"zigbee_dongle_fw_version": "100F"
}
},
"encharge_power": {
"123456": {
"apparent_power_mva": 0,
"real_power_mw": 0,
"soc": 15
}
},
"encharge_aggregate": {
"available_energy": 525,
"backup_reserve": 526,
"state_of_charge": 15,
"reserve_state_of_charge": 15,
"configured_reserve_state_of_charge": 15,
"max_available_capacity": 3500
},
"enpower": {
"grid_mode": "multimode-ongrid",
"admin_state": 24,
"admin_state_str": "ENPWR_STATE_OPER_CLOSED",
"comm_level_2_4_ghz": 5,
"comm_level_sub_ghz": 5,
"communicating": true,
"firmware_loaded_date": 1695330323,
"firmware_version": "1.2.2064_release/20.34",
"installed_date": 1695330323,
"last_report_date": 1695769447,
"mains_admin_state": "closed",
"mains_oper_state": "closed",
"operating": true,
"part_number": "830-01760-r37",
"serial_number": "654321",
"temperature": 79,
"temperature_unit": "F",
"zigbee_dongle_fw_version": "1009"
},
"system_consumption": {
"watt_hours_lifetime": 1234,
"watt_hours_last_7_days": 1234,
"watt_hours_today": 1234,
"watts_now": 1234
},
"system_production": {
"watt_hours_lifetime": 1234,
"watt_hours_last_7_days": 1234,
"watt_hours_today": 1234,
"watts_now": 1234
},
"system_consumption_phases": {
"L1": {
"watt_hours_lifetime": 1322,
"watt_hours_last_7_days": 1321,
"watt_hours_today": 1323,
"watts_now": 1324
},
"L2": {
"watt_hours_lifetime": 2322,
"watt_hours_last_7_days": 2321,
"watt_hours_today": 2323,
"watts_now": 2324
},
"L3": {
"watt_hours_lifetime": 3322,
"watt_hours_last_7_days": 3321,
"watt_hours_today": 3323,
"watts_now": 3324
}
},
"system_production_phases": {
"L1": {
"watt_hours_lifetime": 1232,
"watt_hours_last_7_days": 1231,
"watt_hours_today": 1233,
"watts_now": 1234
},
"L2": {
"watt_hours_lifetime": 2232,
"watt_hours_last_7_days": 2231,
"watt_hours_today": 2233,
"watts_now": 2234
},
"L3": {
"watt_hours_lifetime": 3232,
"watt_hours_last_7_days": 3231,
"watt_hours_today": 3233,
"watts_now": 3234
}
},
"ctmeter_production": {
"eid": "100000010",
"timestamp": 1708006110,
"energy_delivered": 11234,
"energy_received": 12345,
"active_power": 100,
"power_factor": 0.11,
"voltage": 111,
"current": 0.2,
"frequency": 50.1,
"state": "enabled",
"measurement_type": "production",
"metering_status": "normal",
"status_flags": ["production-imbalance", "power-on-unused-phase"]
},
"ctmeter_consumption": {
"eid": "100000020",
"timestamp": 1708006120,
"energy_delivered": 21234,
"energy_received": 22345,
"active_power": 101,
"power_factor": 0.21,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "net-consumption",
"metering_status": "normal",
"status_flags": []
},
"ctmeter_storage": {
"eid": "100000030",
"timestamp": 1708006120,
"energy_delivered": 31234,
"energy_received": 32345,
"active_power": 103,
"power_factor": 0.23,
"voltage": 113,
"current": 0.4,
"frequency": 50.3,
"state": "enabled",
"measurement_type": "storage",
"metering_status": "normal",
"status_flags": []
},
"ctmeter_production_phases": {
"L1": {
"eid": "100000011",
"timestamp": 1708006111,
"energy_delivered": 112341,
"energy_received": 123451,
"active_power": 20,
"power_factor": 0.12,
"voltage": 111,
"current": 0.2,
"frequency": 50.1,
"state": "enabled",
"measurement_type": "production",
"metering_status": "normal",
"status_flags": ["production-imbalance"]
},
"L2": {
"eid": "100000012",
"timestamp": 1708006112,
"energy_delivered": 112342,
"energy_received": 123452,
"active_power": 30,
"power_factor": 0.13,
"voltage": 111,
"current": 0.2,
"frequency": 50.1,
"state": "enabled",
"measurement_type": "production",
"metering_status": "normal",
"status_flags": ["power-on-unused-phase"]
},
"L3": {
"eid": "100000013",
"timestamp": 1708006113,
"energy_delivered": 112343,
"energy_received": 123453,
"active_power": 50,
"power_factor": 0.14,
"voltage": 111,
"current": 0.2,
"frequency": 50.1,
"state": "enabled",
"measurement_type": "production",
"metering_status": "normal",
"status_flags": []
}
},
"ctmeter_consumption_phases": {
"L1": {
"eid": "100000021",
"timestamp": 1708006121,
"energy_delivered": 212341,
"energy_received": 223451,
"active_power": 21,
"power_factor": 0.22,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "net-consumption",
"metering_status": "normal",
"status_flags": []
},
"L2": {
"eid": "100000022",
"timestamp": 1708006122,
"energy_delivered": 212342,
"energy_received": 223452,
"active_power": 31,
"power_factor": 0.23,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "net-consumption",
"metering_status": "normal",
"status_flags": []
},
"L3": {
"eid": "100000023",
"timestamp": 1708006123,
"energy_delivered": 212343,
"energy_received": 223453,
"active_power": 51,
"power_factor": 0.24,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "net-consumption",
"metering_status": "normal",
"status_flags": []
}
},
"ctmeter_storage_phases": {
"L1": {
"eid": "100000031",
"timestamp": 1708006121,
"energy_delivered": 312341,
"energy_received": 323451,
"active_power": 22,
"power_factor": 0.32,
"voltage": 113,
"current": 0.4,
"frequency": 50.3,
"state": "enabled",
"measurement_type": "storage",
"metering_status": "normal",
"status_flags": []
},
"L2": {
"eid": "100000032",
"timestamp": 1708006122,
"energy_delivered": 312342,
"energy_received": 323452,
"active_power": 33,
"power_factor": 0.23,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "storage",
"metering_status": "normal",
"status_flags": []
},
"L3": {
"eid": "100000033",
"timestamp": 1708006123,
"energy_delivered": 312343,
"energy_received": 323453,
"active_power": 53,
"power_factor": 0.24,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "storage",
"metering_status": "normal",
"status_flags": []
}
},
"dry_contact_status": {
"NC1": {
"id": "NC1",
"status": "open"
},
"NC2": {
"id": "NC2",
"status": "closed"
},
"NC3": {
"id": "NC3",
"status": "open"
}
},
"dry_contact_settings": {
"NC1": {
"id": "NC1",
"black_start": 5.0,
"essential_end_time": 32400.0,
"essential_start_time": 57600.0,
"generator_action": "shed",
"grid_action": "shed",
"load_name": "NC1 Fixture",
"manual_override": true,
"micro_grid_action": "shed",
"mode": "manual",
"override": true,
"priority": 1.0,
"pv_serial_nb": [],
"soc_high": 70.0,
"soc_low": 25.0,
"type": "LOAD"
},
"NC2": {
"id": "NC2",
"black_start": 5.0,
"essential_end_time": 57600.0,
"essential_start_time": 32400.0,
"generator_action": "shed",
"grid_action": "apply",
"load_name": "NC2 Fixture",
"manual_override": true,
"micro_grid_action": "shed",
"mode": "manual",
"override": true,
"priority": 2.0,
"pv_serial_nb": [],
"soc_high": 70.0,
"soc_low": 30.0,
"type": "LOAD"
},
"NC3": {
"id": "NC3",
"black_start": 5.0,
"essential_end_time": 57600.0,
"essential_start_time": 32400.0,
"generator_action": "apply",
"grid_action": "shed",
"load_name": "NC3 Fixture",
"manual_override": true,
"micro_grid_action": "apply",
"mode": "manual",
"override": true,
"priority": 3.0,
"pv_serial_nb": [],
"soc_high": 70.0,
"soc_low": 30.0,
"type": "NONE"
}
},
"inverters": {
"1": {
"serial_number": "1",
"last_report_date": 1,
"last_report_watts": 1,
"max_report_watts": 1
}
},
"tariff": {
"currency": {
"code": "EUR"
},
"logger": "mylogger",
"date": "1695744220",
"storage_settings": {
"mode": "self-consumption",
"operation_mode_sub_type": "",
"reserved_soc": 15.0,
"very_low_soc": 5,
"charge_from_grid": true,
"date": "1695598084"
},
"single_rate": {
"rate": 0.0,
"sell": 0.0
},
"seasons": [
{
"id": "season_1",
"start": "1/1",
"days": [
{
"id": "all_days",
"days": "Mon,Tue,Wed,Thu,Fri,Sat,Sun",
"must_charge_start": 444,
"must_charge_duration": 35,
"must_charge_mode": "CG",
"enable_discharge_to_grid": true,
"periods": [
{
"id": "period_1",
"start": 480,
"rate": 0.1898
},
{
"id": "filler",
"start": 1320,
"rate": 0.1034
}
]
}
],
"tiers": []
}
],
"seasons_sell": []
},
"raw": {
"varies_by": "firmware_version"
}
}
}

View File

@ -0,0 +1,260 @@
{
"serial_number": "1234",
"firmware": "7.6.175",
"part_number": "123456789",
"envoy_model": "Envoy, phases: 3, phase mode: three, net-consumption CT, production CT",
"supported_features": 1743,
"phase_mode": "three",
"phase_count": 3,
"active_phase_count": 3,
"ct_meter_count": 2,
"consumption_meter_type": "net-consumption",
"production_meter_type": "production",
"storage_meter_type": null,
"data": {
"encharge_inventory": null,
"encharge_power": null,
"encharge_aggregate": null,
"enpower": null,
"system_consumption": {
"watt_hours_lifetime": 1234,
"watt_hours_last_7_days": 1234,
"watt_hours_today": 1234,
"watts_now": 1234
},
"system_production": {
"watt_hours_lifetime": 1234,
"watt_hours_last_7_days": 1234,
"watt_hours_today": 1234,
"watts_now": 1234
},
"system_consumption_phases": {
"L1": {
"watt_hours_lifetime": 1322,
"watt_hours_last_7_days": 1321,
"watt_hours_today": 1323,
"watts_now": 1324
},
"L2": {
"watt_hours_lifetime": 2322,
"watt_hours_last_7_days": 2321,
"watt_hours_today": 2323,
"watts_now": 2324
},
"L3": {
"watt_hours_lifetime": 3322,
"watt_hours_last_7_days": 3321,
"watt_hours_today": 3323,
"watts_now": 3324
}
},
"system_production_phases": {
"L1": {
"watt_hours_lifetime": 1232,
"watt_hours_last_7_days": 1231,
"watt_hours_today": 1233,
"watts_now": 1234
},
"L2": {
"watt_hours_lifetime": 2232,
"watt_hours_last_7_days": 2231,
"watt_hours_today": 2233,
"watts_now": 2234
},
"L3": {
"watt_hours_lifetime": 3232,
"watt_hours_last_7_days": 3231,
"watt_hours_today": 3233,
"watts_now": 3234
}
},
"ctmeter_production": {
"eid": "100000010",
"timestamp": 1708006110,
"energy_delivered": 11234,
"energy_received": 12345,
"active_power": 100,
"power_factor": 0.11,
"voltage": 111,
"current": 0.2,
"frequency": 50.1,
"state": "enabled",
"measurement_type": "production",
"metering_status": "normal",
"status_flags": ["production-imbalance", "power-on-unused-phase"]
},
"ctmeter_consumption": {
"eid": "100000020",
"timestamp": 1708006120,
"energy_delivered": 21234,
"energy_received": 22345,
"active_power": 101,
"power_factor": 0.21,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "net-consumption",
"metering_status": "normal",
"status_flags": []
},
"ctmeter_storage": null,
"ctmeter_production_phases": {
"L1": {
"eid": "100000011",
"timestamp": 1708006111,
"energy_delivered": 112341,
"energy_received": 123451,
"active_power": 20,
"power_factor": 0.12,
"voltage": 111,
"current": 0.2,
"frequency": 50.1,
"state": "enabled",
"measurement_type": "production",
"metering_status": "normal",
"status_flags": ["production-imbalance"]
},
"L2": {
"eid": "100000012",
"timestamp": 1708006112,
"energy_delivered": 112342,
"energy_received": 123452,
"active_power": 30,
"power_factor": 0.13,
"voltage": 111,
"current": 0.2,
"frequency": 50.1,
"state": "enabled",
"measurement_type": "production",
"metering_status": "normal",
"status_flags": ["power-on-unused-phase"]
},
"L3": {
"eid": "100000013",
"timestamp": 1708006113,
"energy_delivered": 112343,
"energy_received": 123453,
"active_power": 50,
"power_factor": 0.14,
"voltage": 111,
"current": 0.2,
"frequency": 50.1,
"state": "enabled",
"measurement_type": "production",
"metering_status": "normal",
"status_flags": []
}
},
"ctmeter_consumption_phases": {
"L1": {
"eid": "100000021",
"timestamp": 1708006121,
"energy_delivered": 212341,
"energy_received": 223451,
"active_power": 21,
"power_factor": 0.22,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "net-consumption",
"metering_status": "normal",
"status_flags": []
},
"L2": {
"eid": "100000022",
"timestamp": 1708006122,
"energy_delivered": 212342,
"energy_received": 223452,
"active_power": 31,
"power_factor": 0.23,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "net-consumption",
"metering_status": "normal",
"status_flags": []
},
"L3": {
"eid": "100000023",
"timestamp": 1708006123,
"energy_delivered": 212343,
"energy_received": 223453,
"active_power": 51,
"power_factor": 0.24,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "net-consumption",
"metering_status": "normal",
"status_flags": []
}
},
"ctmeter_storage_phases": null,
"dry_contact_status": {},
"dry_contact_settings": {},
"inverters": {
"1": {
"serial_number": "1",
"last_report_date": 1,
"last_report_watts": 1,
"max_report_watts": 1
}
},
"tariff": {
"currency": {
"code": "EUR"
},
"logger": "mylogger",
"date": "1695744220",
"storage_settings": {
"mode": "self-consumption",
"operation_mode_sub_type": "",
"reserved_soc": 15.0,
"very_low_soc": 5,
"charge_from_grid": true,
"date": "1695598084"
},
"single_rate": {
"rate": 0.0,
"sell": 0.0
},
"seasons": [
{
"id": "season_1",
"start": "1/1",
"days": [
{
"id": "all_days",
"days": "Mon,Tue,Wed,Thu,Fri,Sat,Sun",
"must_charge_start": 444,
"must_charge_duration": 35,
"must_charge_mode": "CG",
"enable_discharge_to_grid": true,
"periods": [
{
"id": "period_1",
"start": 480,
"rate": 0.1898
},
{
"id": "filler",
"start": 1320,
"rate": 0.1034
}
]
}
],
"tiers": []
}
],
"seasons_sell": []
},
"raw": {
"varies_by": "firmware_version"
}
}
}

View File

@ -0,0 +1,125 @@
{
"serial_number": "1234",
"firmware": "7.6.175",
"part_number": "123456789",
"envoy_model": "Envoy, phases: 1, phase mode: three, total-consumption CT, production CT",
"supported_features": 1217,
"phase_mode": "three",
"phase_count": 1,
"active_phase_count": 0,
"ct_meter_count": 2,
"consumption_meter_type": "total-consumption",
"production_meter_type": "production",
"storage_meter_type": null,
"data": {
"encharge_inventory": null,
"encharge_power": null,
"encharge_aggregate": null,
"enpower": null,
"system_consumption": null,
"system_production": {
"watt_hours_lifetime": 1234,
"watt_hours_last_7_days": 1234,
"watt_hours_today": 1234,
"watts_now": 1234
},
"system_consumption_phases": null,
"system_production_phases": null,
"ctmeter_production": {
"eid": "100000010",
"timestamp": 1708006110,
"energy_delivered": 11234,
"energy_received": 12345,
"active_power": 100,
"power_factor": 0.11,
"voltage": 111,
"current": 0.2,
"frequency": 50.1,
"state": "enabled",
"measurement_type": "production",
"metering_status": "normal",
"status_flags": ["production-imbalance", "power-on-unused-phase"]
},
"ctmeter_consumption": {
"eid": "100000020",
"timestamp": 1708006120,
"energy_delivered": 21234,
"energy_received": 22345,
"active_power": 101,
"power_factor": 0.21,
"voltage": 112,
"current": 0.3,
"frequency": 50.2,
"state": "enabled",
"measurement_type": "total-consumption",
"metering_status": "normal",
"status_flags": []
},
"ctmeter_storage": null,
"ctmeter_production_phases": null,
"ctmeter_consumption_phases": null,
"ctmeter_storage_phases": null,
"dry_contact_status": {},
"dry_contact_settings": {},
"inverters": {
"1": {
"serial_number": "1",
"last_report_date": 1,
"last_report_watts": 1,
"max_report_watts": 1
}
},
"tariff": {
"currency": {
"code": "EUR"
},
"logger": "mylogger",
"date": "1695744220",
"storage_settings": {
"mode": "self-consumption",
"operation_mode_sub_type": "",
"reserved_soc": 15.0,
"very_low_soc": 5,
"charge_from_grid": true,
"date": "1695598084"
},
"single_rate": {
"rate": 0.0,
"sell": 0.0
},
"seasons": [
{
"id": "season_1",
"start": "1/1",
"days": [
{
"id": "all_days",
"days": "Mon,Tue,Wed,Thu,Fri,Sat,Sun",
"must_charge_start": 444,
"must_charge_duration": 35,
"must_charge_mode": "CG",
"enable_discharge_to_grid": true,
"periods": [
{
"id": "period_1",
"start": 480,
"rate": 0.1898
},
{
"id": "filler",
"start": 1320,
"rate": 0.1034
}
]
}
],
"tiers": []
}
],
"seasons_sell": []
},
"raw": {
"varies_by": "firmware_version"
}
}
}

View File

@ -1,10 +0,0 @@
# serializer version: 1
# name: test_platforms
list([
<Platform.BINARY_SENSOR: 'binary_sensor'>,
<Platform.NUMBER: 'number'>,
<Platform.SELECT: 'select'>,
<Platform.SENSOR: 'sensor'>,
<Platform.SWITCH: 'switch'>,
])
# ---

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
"""Test Enphase Envoy diagnostics.""" """Test Enphase Envoy diagnostics."""
from unittest.mock import AsyncMock, patch from unittest.mock import AsyncMock
from pyenphase.exceptions import EnvoyError from pyenphase.exceptions import EnvoyError
import pytest import pytest
@ -10,9 +10,9 @@ from homeassistant.components.enphase_envoy.const import (
DOMAIN, DOMAIN,
OPTION_DIAGNOSTICS_INCLUDE_FIXTURES, OPTION_DIAGNOSTICS_INCLUDE_FIXTURES,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from . import setup_integration
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
from tests.components.diagnostics import get_diagnostics_for_config_entry from tests.components.diagnostics import get_diagnostics_for_config_entry
@ -36,85 +36,55 @@ def limit_diagnostic_attrs(prop, path) -> bool:
async def test_entry_diagnostics( async def test_entry_diagnostics(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: MockConfigEntry,
hass_client: ClientSessionGenerator, hass_client: ClientSessionGenerator,
setup_enphase_envoy, mock_envoy: AsyncMock,
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test config entry diagnostics.""" """Test config entry diagnostics."""
await setup_integration(hass, config_entry)
assert await get_diagnostics_for_config_entry( assert await get_diagnostics_for_config_entry(
hass, hass_client, config_entry hass, hass_client, config_entry
) == snapshot(exclude=limit_diagnostic_attrs) ) == snapshot(exclude=limit_diagnostic_attrs)
@pytest.fixture(name="config_entry_options") @pytest.fixture(name="config_entry_options")
def config_entry_options_fixture(hass: HomeAssistant, config, serial_number): def config_entry_options_fixture(hass: HomeAssistant, config: dict[str, str]):
"""Define a config entry fixture.""" """Define a config entry fixture."""
entry = MockConfigEntry( return MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,
entry_id="45a36e55aaddb2007c5f6602e0c38e72", entry_id="45a36e55aaddb2007c5f6602e0c38e72",
title=f"Envoy {serial_number}" if serial_number else "Envoy", title="Envoy 1234",
unique_id=serial_number, unique_id="1234",
data=config, data=config,
options={OPTION_DIAGNOSTICS_INCLUDE_FIXTURES: True}, options={OPTION_DIAGNOSTICS_INCLUDE_FIXTURES: True},
) )
entry.add_to_hass(hass)
return entry
async def test_entry_diagnostics_with_fixtures( async def test_entry_diagnostics_with_fixtures(
hass: HomeAssistant, hass: HomeAssistant,
hass_client: ClientSessionGenerator, hass_client: ClientSessionGenerator,
config_entry_options: ConfigEntry, config_entry_options: MockConfigEntry,
setup_enphase_envoy, mock_envoy: AsyncMock,
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test config entry diagnostics.""" """Test config entry diagnostics."""
await setup_integration(hass, config_entry_options)
assert await get_diagnostics_for_config_entry( assert await get_diagnostics_for_config_entry(
hass, hass_client, config_entry_options hass, hass_client, config_entry_options
) == snapshot(exclude=limit_diagnostic_attrs) ) == snapshot(exclude=limit_diagnostic_attrs)
@pytest.fixture(name="setup_enphase_envoy_options_error")
async def setup_enphase_envoy_options_error_fixture(
hass: HomeAssistant,
config,
mock_envoy_options_error,
):
"""Define a fixture to set up Enphase Envoy."""
with (
patch(
"homeassistant.components.enphase_envoy.config_flow.Envoy",
return_value=mock_envoy_options_error,
),
patch(
"homeassistant.components.enphase_envoy.Envoy",
return_value=mock_envoy_options_error,
),
):
assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
yield
@pytest.fixture(name="mock_envoy_options_error")
def mock_envoy_options_fixture(
mock_envoy,
):
"""Mock envoy with error in request."""
mock_envoy_options = mock_envoy
mock_envoy_options.request.side_effect = AsyncMock(side_effect=EnvoyError("Test"))
return mock_envoy_options
async def test_entry_diagnostics_with_fixtures_with_error( async def test_entry_diagnostics_with_fixtures_with_error(
hass: HomeAssistant, hass: HomeAssistant,
hass_client: ClientSessionGenerator, hass_client: ClientSessionGenerator,
config_entry_options: ConfigEntry, config_entry_options: MockConfigEntry,
setup_enphase_envoy_options_error,
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
mock_envoy: AsyncMock,
) -> None: ) -> None:
"""Test config entry diagnostics.""" """Test config entry diagnostics."""
await setup_integration(hass, config_entry_options)
mock_envoy.request.side_effect = EnvoyError("Test")
assert await get_diagnostics_for_config_entry( assert await get_diagnostics_for_config_entry(
hass, hass_client, config_entry_options hass, hass_client, config_entry_options
) == snapshot(exclude=limit_diagnostic_attrs) ) == snapshot(exclude=limit_diagnostic_attrs)

View File

@ -1,61 +1,39 @@
"""Test Enphase Envoy sensors.""" """Test Enphase Envoy sensors."""
from collections.abc import AsyncGenerator from unittest.mock import AsyncMock, patch
from unittest.mock import Mock, patch
import pytest import pytest
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
from homeassistant.components.enphase_envoy import DOMAIN
from homeassistant.components.enphase_envoy.const import Platform from homeassistant.components.enphase_envoy.const import Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry from . import setup_integration
from tests.common import MockConfigEntry, snapshot_platform
@pytest.fixture(name="setup_enphase_envoy_sensor")
async def setup_enphase_envoy_sensor_fixture(
hass: HomeAssistant, config: dict[str, str], mock_envoy: Mock
) -> AsyncGenerator[None]:
"""Define a fixture to set up Enphase Envoy with sensor platform only."""
with (
patch(
"homeassistant.components.enphase_envoy.config_flow.Envoy",
return_value=mock_envoy,
),
patch(
"homeassistant.components.enphase_envoy.Envoy",
return_value=mock_envoy,
),
patch(
"homeassistant.components.enphase_envoy.PLATFORMS",
[Platform.SENSOR],
),
):
assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
yield
@pytest.mark.parametrize(
("mock_envoy"),
[
"envoy",
"envoy_1p_metered",
"envoy_metered_batt_relay",
"envoy_nobatt_metered_3p",
"envoy_tot_cons_metered",
],
indirect=["mock_envoy"],
)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_sensor( async def test_sensor(
hass: HomeAssistant, hass: HomeAssistant,
entity_registry: er.EntityRegistry,
config_entry: MockConfigEntry,
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
setup_enphase_envoy_sensor: None, mock_envoy: AsyncMock,
config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
) -> None: ) -> None:
"""Test enphase_envoy sensor entities.""" """Test sensor platform entities against snapshot."""
# compare registered entities against snapshot of prior run with patch("homeassistant.components.enphase_envoy.PLATFORMS", [Platform.SENSOR]):
entity_entries = er.async_entries_for_config_entry( await setup_integration(hass, config_entry)
entity_registry, config_entry.entry_id await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
)
assert entity_entries
assert entity_entries == snapshot
# Test if all entities still have same state
for entity_entry in entity_entries:
assert hass.states.get(entity_entry.entity_id) == snapshot(
name=f"{entity_entry.entity_id}-state"
)