fix(config_flow): D3 — await the discovery-dedup coroutine (t37)
`ConfigFlow._async_handle_discovery_without_unique_id` is an `async def` in core (verified: `inspect.iscoroutinefunction` is True) and core awaits it. t32 called it without `await`, so the coroutine body never ran: no `already_configured` abort when the handler already had entries, no `DEFAULT_DISCOVERY_UNIQUE_ID` claim, no `already_in_progress` abort — HA's discovery dedup was dead, Python warned "coroutine ... was never awaited", and the host-equality loop that used to sit here was the only accidental dedup. The call is awaited and the now-unreachable host loop is gone (the real helper is stricter: any entry for the domain, or any in-flight flow). The harness mirrors the real contract instead of a sync no-op: * `entity_stublib`'s hub stub makes the helper a coroutine (a sync stub would turn the production `await` into a TypeError); * `test_standalone_setup`'s stub models the real semantics — a coroutine raising `DiscoveryDedupAbortError` (core raises AbortFlow), driven by the shared holder's entry list and in-progress list — and its tests now assert all three outcomes: awaited-and-proceeds (counter + claimed discovery unique id), `already_configured` when entries exist, `already_in_progress` when another flow runs. A fourth test collects the un-awaited-coroutine warning, and the prefill test in the UX suite asserts the awaited counter. Red proof: with the pre-fix config_flow.py the repo-owned sweep reports `config_flow.py:425: missing-await: self._async_handle_discovery_without_unique_id()`. Verified: 289 passed, 2 skipped (D3 stage); ruff clean.
This commit is contained in:
1 parent
bd72ae3170
commit
60fb4f7557
4 files changed
+115
-34
No files matched your search
@@ -207,9 +207,13 @@ def install() -> None:
|
||||
async_set_unique_id = _stub_set_unique_id
|
||||
_abort_if_unique_id_configured = _noop_abort
|
||||
|
||||
def _async_handle_discovery_without_unique_id(self):
|
||||
# t32 F2 (audited helper): recording no-op at hub scope
|
||||
pass
|
||||
async def _async_handle_discovery_without_unique_id(self):
|
||||
# t37 D3: the real helper is a COROUTINE and core awaits it — a
|
||||
# sync stub here would turn the production `await` into a
|
||||
# TypeError. The abort semantics live in
|
||||
# tests/test_standalone_setup.py, whose stub owns entry/in-progress
|
||||
# state; at hub scope there is nothing to abort on.
|
||||
return None
|
||||
|
||||
def async_show_form(
|
||||
self, *, step_id, data_schema=None, errors=None,
|
||||
|
||||
Reference in new issue
Block a user