HA improvements: entity overflow fix, live % fetch on device page, searchable entity dropdown

This commit is contained in:
2026-04-14 01:17:53 -05:00
parent d7ba64a2f3
commit b6a3533fed
4 changed files with 184 additions and 6 deletions
+77
View File
@@ -470,3 +470,80 @@ def test_manual_edit_no_log_when_unchanged(ha_client_f):
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
# ---------------------------------------------------------------------------
# Group 5 — live fetch on device page load + /ha/entities endpoint
# ---------------------------------------------------------------------------
def test_device_detail_shows_live_pct(ha_app, ha_client_f):
"""Opening a device page fetches live % from HA and displays it."""
ha_client_f.post("/device/add", data={"name": "Dev Live", "battery_slots": "1"})
ha_client_f.post("/device/1/edit", data={
"name": "Dev Live", "battery_slots": "1", "ha_entity_id": "sensor.live_test"
})
mock_resp = MagicMock()
mock_resp.json.return_value = {"state": "78", "entity_id": "sensor.live_test"}
mock_resp.raise_for_status.return_value = None
with patch("ha_client.requests.get", return_value=mock_resp):
resp = ha_client_f.get("/device/1")
assert resp.status_code == 200
assert b"78%" in resp.data
def test_device_detail_updates_battery_on_load(ha_app, ha_client_f):
"""Battery percentage is updated (with pct_log) when device page is loaded and value changed."""
ha_client_f.post("/device/add", data={"name": "Dev Update", "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 Update", "battery_slots": "1", "ha_entity_id": "sensor.update_test"
})
mock_resp = MagicMock()
mock_resp.json.return_value = {"state": "63"}
mock_resp.raise_for_status.return_value = None
with patch("ha_client.requests.get", return_value=mock_resp):
ha_client_f.get("/device/1")
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)()
b = s.get(Battery, 1)
assert b.battery_percentage == 63
logs = s.query(BatteryPctLog).filter_by(battery_id=1, source="poll").all()
assert len(logs) == 1
assert logs[0].percentage == 63
s.close()
def test_ha_entities_endpoint(ha_app, ha_client_f):
"""GET /ha/entities returns only battery-related entities from HA."""
mock_resp = MagicMock()
mock_resp.json.return_value = [
{"entity_id": "sensor.tv_battery", "attributes": {"device_class": "battery", "friendly_name": "TV Battery"}},
{"entity_id": "sensor.remote_battery", "attributes": {"friendly_name": "Remote"}}, # 'battery' in id
{"entity_id": "sensor.temperature", "attributes": {"device_class": "temperature", "friendly_name": "Temp"}},
{"entity_id": "light.living_room", "attributes": {}},
]
mock_resp.raise_for_status.return_value = None
with patch("ha_client.requests.get", return_value=mock_resp):
resp = ha_client_f.get("/ha/entities")
assert resp.status_code == 200
data = resp.get_json()
entity_ids = [e["entity_id"] for e in data]
assert "sensor.tv_battery" in entity_ids
assert "sensor.remote_battery" in entity_ids
assert "sensor.temperature" not in entity_ids
assert "light.living_room" not in entity_ids
# friendly names present
tv = next(e for e in data if e["entity_id"] == "sensor.tv_battery")
assert tv["friendly_name"] == "TV Battery"