95 lines
2.9 KiB
Python
95 lines
2.9 KiB
Python
"""Stub out homeassistant before any local imports so tests run without HA installed."""
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from datetime import timedelta
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# HA module stubs — must happen before coordinator.py is imported
|
|
# ---------------------------------------------------------------------------
|
|
|
|
class _DataUpdateCoordinator:
|
|
"""Minimal stand-in for DataUpdateCoordinator."""
|
|
def __init__(self, hass, logger, *, name, update_interval):
|
|
self.hass = hass
|
|
self.name = name
|
|
self.data: dict = {}
|
|
|
|
|
|
class _UpdateFailed(Exception):
|
|
pass
|
|
|
|
|
|
_update_coordinator_stub = MagicMock()
|
|
_update_coordinator_stub.DataUpdateCoordinator = _DataUpdateCoordinator
|
|
_update_coordinator_stub.UpdateFailed = _UpdateFailed
|
|
|
|
for _mod in [
|
|
"homeassistant",
|
|
"homeassistant.config_entries",
|
|
"homeassistant.core",
|
|
"homeassistant.components",
|
|
"homeassistant.components.sensor",
|
|
"homeassistant.components.switch",
|
|
"homeassistant.const",
|
|
"homeassistant.helpers",
|
|
"homeassistant.helpers.device_registry",
|
|
"homeassistant.helpers.entity_platform",
|
|
"homeassistant.helpers.restore_state",
|
|
"homeassistant.helpers.selector",
|
|
"voluptuous",
|
|
]:
|
|
sys.modules.setdefault(_mod, MagicMock())
|
|
|
|
sys.modules["homeassistant.helpers.update_coordinator"] = _update_coordinator_stub
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Shared test fixtures
|
|
# ---------------------------------------------------------------------------
|
|
|
|
from custom_components.easee_solar_charging.coordinator import EaseeSolarCoordinator # noqa: E402
|
|
from custom_components.easee_solar_charging.const import ( # noqa: E402
|
|
CONF_STOP_GRACE_MINUTES,
|
|
DEFAULT_STOP_GRACE_MINUTES,
|
|
)
|
|
|
|
CHARGER_ID = "ehxt9pqp"
|
|
SOLAR_SENSOR = "sensor.solar_excess"
|
|
|
|
|
|
class FakeCoordinator(EaseeSolarCoordinator):
|
|
"""Coordinator with HA wiring stripped out so logic methods can be unit-tested."""
|
|
|
|
def __init__(self, options: dict | None = None) -> None:
|
|
# Skip DataUpdateCoordinator.__init__ — not needed for logic-only tests.
|
|
self.hass = MagicMock()
|
|
self.charger_id = CHARGER_ID
|
|
self._solar_excess_sensor = SOLAR_SENSOR
|
|
self._device_id = None
|
|
self._last_sent_current = None
|
|
self._last_sent_at = None
|
|
self._below_threshold_since = None
|
|
self.solar_charging_enabled = True
|
|
self.stop_grace_enabled = True
|
|
self._entry = MagicMock()
|
|
self._entry.options = options if options is not None else {
|
|
CONF_STOP_GRACE_MINUTES: DEFAULT_STOP_GRACE_MINUTES,
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def coord() -> FakeCoordinator:
|
|
return FakeCoordinator()
|
|
|
|
|
|
def make_state(value: str) -> MagicMock:
|
|
"""Return a minimal HA state mock with the given state string."""
|
|
s = MagicMock()
|
|
s.state = value
|
|
return s
|