Track battery percentage history; skip poll write when value unchanged

This commit is contained in:
2026-04-13 21:15:19 -05:00
parent 279a1f3f3e
commit d7ba64a2f3
6 changed files with 230 additions and 7 deletions
+106 -2
View File
@@ -364,5 +364,109 @@ def test_manual_battery_percentage_edit(ha_client_f):
# Clear via edit form
ha_client_f.post("/battery/1/edit-details", data={"battery_percentage": ""})
resp2 = ha_client_f.get("/battery/1")
# percentage display row should not appear when None
assert b"Battery %" not in resp2.data or b"55%" not in resp2.data
# "55%" still appears once in history; the info-table row is gone (current value is None)
assert resp2.data.count(b"55%") == 1
# ---------------------------------------------------------------------------
# Group 3 additions — skip-on-no-change + history logging (poller)
# ---------------------------------------------------------------------------
def test_poll_skips_update_when_percentage_unchanged(ha_app, ha_client_f):
"""No write and no pct_log entry when the polled value matches the stored value."""
ha_client_f.post("/device/add", data={"name": "Dev NoCh", "battery_slots": "1"})
ha_client_f.post("/battery/add", data={"brand": "X", "count": "1"})
ha_client_f.post("/battery/1/assign", data={"device_id": "1"})
ha_client_f.post("/device/1/edit", data={
"name": "Dev NoCh", "battery_slots": "1", "ha_entity_id": "sensor.noch"
})
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from models import Battery, BatteryPctLog
engine = create_engine(ha_app.config["SQLALCHEMY_DATABASE_URI"])
s = sessionmaker(bind=engine)()
s.get(Battery, 1).battery_percentage = 50
s.commit(); s.close()
from ha_client import HomeAssistantClient
from ha_poller import HaPoller
mock_ha = MagicMock(spec=HomeAssistantClient)
mock_ha.enabled = True
mock_ha.get_state.return_value = 50 # same value — should be a no-op
Session = _make_session_factory(ha_app)
HaPoller(mock_ha, Session, interval=300)._poll_once()
s2 = sessionmaker(bind=engine)()
assert s2.query(BatteryPctLog).count() == 0
s2.close()
def test_poll_creates_pct_log_on_change(ha_app, ha_client_f):
"""A pct_log entry with source='poll' is written when the value changes."""
ha_client_f.post("/device/add", data={"name": "Dev Chg", "battery_slots": "1"})
ha_client_f.post("/battery/add", data={"brand": "X", "count": "1"})
ha_client_f.post("/battery/1/assign", data={"device_id": "1"})
ha_client_f.post("/device/1/edit", data={
"name": "Dev Chg", "battery_slots": "1", "ha_entity_id": "sensor.chg"
})
from ha_client import HomeAssistantClient
from ha_poller import HaPoller
from models import BatteryPctLog
mock_ha = MagicMock(spec=HomeAssistantClient)
mock_ha.enabled = True
mock_ha.get_state.return_value = 72
Session = _make_session_factory(ha_app)
HaPoller(mock_ha, Session, interval=300)._poll_once()
s = Session()
logs = s.query(BatteryPctLog).filter_by(battery_id=1).all()
assert len(logs) == 1
assert logs[0].percentage == 72
assert logs[0].source == "poll"
s.close()
# ---------------------------------------------------------------------------
# Group 4 additions — history logging (routes / UI)
# ---------------------------------------------------------------------------
def test_charge_log_creates_pct_log_entry(ha_app, ha_client_f):
"""Logging a charge creates a pct_log entry with percentage=100, source='charge'."""
ha_client_f.post("/battery/add", data={"brand": "X", "count": "1"})
ha_client_f.post("/battery/1/charge-log/add", data={"charged_date": "2026-04-13"})
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from models import BatteryPctLog
engine = create_engine(ha_app.config["SQLALCHEMY_DATABASE_URI"])
s = sessionmaker(bind=engine)()
logs = s.query(BatteryPctLog).filter_by(battery_id=1).all()
assert len(logs) == 1
assert logs[0].percentage == 100
assert logs[0].source == "charge"
s.close()
def test_manual_edit_creates_pct_log_entry(ha_client_f):
"""Saving a new battery_percentage via edit-details creates a history entry."""
ha_client_f.post("/battery/add", data={"brand": "X", "count": "1"})
ha_client_f.post("/battery/1/edit-details", data={"battery_percentage": "65"})
resp = ha_client_f.get("/battery/1")
assert b"65%" in resp.data
assert b"manual" in resp.data # source shown in history table
def test_manual_edit_no_log_when_unchanged(ha_client_f):
"""Saving the same percentage twice produces only one history entry."""
ha_client_f.post("/battery/add", data={"brand": "X", "count": "1"})
ha_client_f.post("/battery/1/edit-details", data={"battery_percentage": "40"})
ha_client_f.post("/battery/1/edit-details", data={"battery_percentage": "40"})
resp = ha_client_f.get("/battery/1")
# "40%" appears once in the info section and once in history — not twice in history
assert resp.data.count(b"40%") == 2