core/tests/components/fronius/test_init.py

167 lines
5.8 KiB
Python

"""Test the Fronius integration."""
from datetime import timedelta
from unittest.mock import patch
from pyfronius import FroniusError
from homeassistant.components.fronius.const import DOMAIN, SOLAR_NET_RESCAN_TIMER
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
from . import mock_responses, setup_fronius_integration
from tests.common import async_fire_time_changed
from tests.test_util.aiohttp import AiohttpClientMocker
from tests.typing import WebSocketGenerator
async def test_unload_config_entry(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test that configuration entry supports unloading."""
mock_responses(aioclient_mock)
await setup_fronius_integration(hass)
fronius_entries = hass.config_entries.async_entries(DOMAIN)
assert len(fronius_entries) == 1
test_entry = fronius_entries[0]
assert test_entry.state is ConfigEntryState.LOADED
assert await hass.config_entries.async_unload(test_entry.entry_id)
await hass.async_block_till_done()
assert test_entry.state is ConfigEntryState.NOT_LOADED
assert not hass.data.get(DOMAIN)
async def test_logger_error(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test setup when logger reports an error."""
# gen24 dataset will raise FroniusError when logger is called
mock_responses(aioclient_mock, fixture_set="gen24")
config_entry = await setup_fronius_integration(hass, is_logger=True)
assert config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_inverter_error(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test setup when inverter_info reports an error."""
mock_responses(aioclient_mock)
with patch(
"pyfronius.Fronius.inverter_info",
side_effect=FroniusError,
):
config_entry = await setup_fronius_integration(hass)
assert config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_inverter_night_rescan(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
aioclient_mock: AiohttpClientMocker,
) -> None:
"""Test dynamic adding of an inverter discovered automatically after a Home Assistant reboot during the night."""
mock_responses(aioclient_mock, fixture_set="igplus_v2", night=True)
config_entry = await setup_fronius_integration(hass, is_logger=True)
assert config_entry.state is ConfigEntryState.LOADED
# Only expect logger during the night
fronius_entries = hass.config_entries.async_entries(DOMAIN)
assert len(fronius_entries) == 1
# Switch to daytime
mock_responses(aioclient_mock, fixture_set="igplus_v2", night=False)
async_fire_time_changed(
hass, dt_util.utcnow() + timedelta(minutes=SOLAR_NET_RESCAN_TIMER)
)
await hass.async_block_till_done()
# We expect our inverter to be present now
inverter_1 = device_registry.async_get_device(identifiers={(DOMAIN, "203200")})
assert inverter_1.manufacturer == "Fronius"
# After another re-scan we still only expect this inverter
async_fire_time_changed(
hass, dt_util.utcnow() + timedelta(minutes=SOLAR_NET_RESCAN_TIMER * 2)
)
await hass.async_block_till_done()
inverter_1 = device_registry.async_get_device(identifiers={(DOMAIN, "203200")})
assert inverter_1.manufacturer == "Fronius"
async def test_inverter_rescan_interruption(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
aioclient_mock: AiohttpClientMocker,
) -> None:
"""Test interruption of re-scan during runtime to process further."""
mock_responses(aioclient_mock, fixture_set="igplus_v2", night=True)
config_entry = await setup_fronius_integration(hass, is_logger=True)
assert config_entry.state is ConfigEntryState.LOADED
# Expect 1 devices during the night, logger
assert (
len(dr.async_entries_for_config_entry(device_registry, config_entry.entry_id))
== 1
)
with patch(
"pyfronius.Fronius.inverter_info",
side_effect=FroniusError,
):
async_fire_time_changed(
hass, dt_util.utcnow() + timedelta(minutes=SOLAR_NET_RESCAN_TIMER)
)
await hass.async_block_till_done()
# No increase of devices expected because of a FroniusError
assert (
len(
dr.async_entries_for_config_entry(
device_registry, config_entry.entry_id
)
)
== 1
)
# Next re-scan will pick up the new inverter. Expect 2 devices now.
mock_responses(aioclient_mock, fixture_set="igplus_v2", night=False)
async_fire_time_changed(
hass, dt_util.utcnow() + timedelta(minutes=SOLAR_NET_RESCAN_TIMER * 2)
)
await hass.async_block_till_done()
assert (
len(dr.async_entries_for_config_entry(device_registry, config_entry.entry_id))
== 2
)
async def test_device_remove_devices(
hass: HomeAssistant,
aioclient_mock: AiohttpClientMocker,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
hass_ws_client: WebSocketGenerator,
) -> None:
"""Test we can remove a device."""
assert await async_setup_component(hass, "config", {})
mock_responses(aioclient_mock, fixture_set="gen24_storage")
config_entry = await setup_fronius_integration(
hass, is_logger=False, unique_id="12345678"
)
inverter_1 = device_registry.async_get_device(identifiers={(DOMAIN, "12345678")})
client = await hass_ws_client(hass)
response = await client.remove_device(inverter_1.id, config_entry.entry_id)
assert response["success"]
assert not device_registry.async_get_device(identifiers={(DOMAIN, "12345678")})