hass.tibber_prices/tests/services/test_power_scheduler.py
Julian Pawlowski bb8f5aa8cc
Some checks failed
Validate / HACS validation (push) Has been cancelled
Lint / Ruff (push) Has been cancelled
Validate / Hassfest validation (push) Has been cancelled
chore(testing): add optional Pyright checks for tests
Add a dedicated type-check-tests helper, wire it into check-all behind --with-test-types, and align the affected tests with current typing and helper contracts.

Impact: No direct user-facing change.

User-Impact: none
2026-04-25 22:46:43 +00:00

79 lines
2.6 KiB
Python

"""Unit tests for charging power scheduling helpers."""
from __future__ import annotations
from datetime import UTC, datetime, timedelta
from zoneinfo import ZoneInfo
from custom_components.tibber_prices.services.charging.deadline_solver import resolve_deadline
from custom_components.tibber_prices.services.charging.power_scheduler import build_power_schedule
def _make_intervals(prices: list[float]) -> list[dict[str, object]]:
base = datetime(2026, 1, 1, 0, 0, tzinfo=UTC)
return [
{
"startsAt": (base + timedelta(minutes=15 * index)).isoformat(),
"total": price,
"level": "NORMAL",
}
for index, price in enumerate(prices)
]
def test_continuous_mode_uses_partial_last_interval_power() -> None:
"""Continuous mode should reduce the last interval power when possible."""
result = build_power_schedule(
_make_intervals([0.20, 0.10, 0.15]),
2.5,
max_charge_power_w=4000,
min_charge_power_w=1000,
charging_efficiency=1.0,
)
assert result["mode"] == "continuous"
assert result["total_grid_energy_kwh"] == 2.5
assert sorted(interval["power_w"] for interval in result["intervals"]) == [2000, 4000, 4000]
def test_stepped_mode_uses_smallest_sufficient_step() -> None:
"""Stepped mode should choose the smallest allowed step that finishes the plan."""
result = build_power_schedule(
_make_intervals([0.20, 0.10, 0.15]),
2.5,
max_charge_power_w=4000,
charge_power_steps_w=[1000, 2000, 4000],
charging_efficiency=1.0,
)
assert result["mode"] == "stepped"
assert result["total_grid_energy_kwh"] == 2.5
assert sorted(interval["power_w"] for interval in result["intervals"]) == [2000, 4000, 4000]
def test_resolve_deadline_next_peak_period() -> None:
"""Deadline helper should resolve the next future peak period start."""
now = datetime(2026, 1, 1, 0, 0, tzinfo=UTC)
home_tz = ZoneInfo("UTC")
coordinator_data = {
"pricePeriods": {
"peak_price": {
"periods": [
{
"start": datetime(2026, 1, 1, 1, 0, tzinfo=UTC),
"end": datetime(2026, 1, 1, 2, 0, tzinfo=UTC),
}
]
}
}
}
deadline, source = resolve_deadline(
coordinator_data=coordinator_data,
now=now,
home_tz=home_tz,
must_reach_by_event="next_peak_period",
)
assert deadline == datetime(2026, 1, 1, 1, 0, tzinfo=UTC)
assert source == "next_peak_period"