mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 16:38:31 +00:00
Test harness: run async recorder regressions on a private event loop
asyncio.run() clears the thread's current-loop slot when it finishes; the CI HA harness keeps a session event loop, so every test that followed the new HP-1540-05 regression failed at SETUP with 'There is no current event loop'. The pure-only local run never sees the harness and stayed green — which is exactly how it slipped through. The regressions now spin up an isolated loop and leave the ambient one untouched.
This commit is contained in:
@@ -156,6 +156,23 @@ def test_unavailable_vacuum_is_no_verdict():
|
|||||||
|
|
||||||
# ---------------- v1.54.0 audit regressions ----------------
|
# ---------------- v1.54.0 audit regressions ----------------
|
||||||
|
|
||||||
|
def _run_isolated(coro):
|
||||||
|
"""Run a coroutine on a private loop WITHOUT touching the ambient one.
|
||||||
|
|
||||||
|
asyncio.run() clears the thread's current-loop slot when it finishes; in
|
||||||
|
the CI HA harness (pytest-asyncio keeps a session event loop) that
|
||||||
|
poisoned the setup of every test that followed — 'There is no current
|
||||||
|
event loop in thread MainThread' across whole files.
|
||||||
|
"""
|
||||||
|
import asyncio
|
||||||
|
loop = asyncio.new_event_loop()
|
||||||
|
try:
|
||||||
|
return loop.run_until_complete(coro)
|
||||||
|
finally:
|
||||||
|
loop.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_map_index_zero_matches_frontend_contract():
|
def test_map_index_zero_matches_frontend_contract():
|
||||||
# HP-1540-02: `map_index: 0` is a VALID first map. The old or-chain
|
# HP-1540-02: `map_index: 0` is a VALID first map. The old or-chain
|
||||||
@@ -235,7 +252,7 @@ def test_refresh_builds_pair_lists_and_dedups_subscription():
|
|||||||
"camera.map": S("idle", {}),
|
"camera.map": S("idle", {}),
|
||||||
})
|
})
|
||||||
rec = trails.TrailRecorder(hass, RT())
|
rec = trails.TrailRecorder(hass, RT())
|
||||||
asyncio.run(rec.async_refresh())
|
_run_isolated(rec.async_refresh())
|
||||||
assert rec.pairs == {"camera.map": [("m_f1", "vacuum.x50"), ("m_f2", "vacuum.x50")]}
|
assert rec.pairs == {"camera.map": [("m_f1", "vacuum.x50"), ("m_f2", "vacuum.x50")]}
|
||||||
assert tracked == [["camera.map", "vacuum.x50"]]
|
assert tracked == [["camera.map", "vacuum.x50"]]
|
||||||
finally:
|
finally:
|
||||||
@@ -297,6 +314,6 @@ def test_overlapping_refreshes_leave_one_subscription_teardown_zero():
|
|||||||
await t3
|
await t3
|
||||||
assert active == [], f"teardown must leave zero subscriptions, got {active}"
|
assert active == [], f"teardown must leave zero subscriptions, got {active}"
|
||||||
|
|
||||||
asyncio.run(scenario())
|
_run_isolated(scenario())
|
||||||
finally:
|
finally:
|
||||||
trails.async_track_state_change_event = old_track
|
trails.async_track_state_change_event = old_track
|
||||||
|
|||||||
Reference in New Issue
Block a user