HA improvements: entity overflow fix, live % fetch on device page, searchable entity dropdown
This commit is contained in:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user