fix(config-flow): the setup menu was unreachable under real HA (t57 UNIT 0a)
t61 F1 (BLOCKER) + F2 + F3 + F5, all reproduced against a real FlowManager
before fixing. The OPTIONS flow was verified good and is untouched by this
commit; the SETUP flow was broken in three independent ways.
F1 — `_show_setup_menu` passed `errors=` to `async_show_menu`, which has no
such parameter (HA 2026.10.1: step_id / menu_options / sort /
description_placeholders). Every path that went near the menu therefore
raised `TypeError` the moment the first form was submitted or ADB pairing
was skipped. The path map, driven end to end: FOUR of the five ordinary
paths died before create_entry ("ADB skip", "ADB paired + protocol off",
"ADB skip + protocol skip", "pair ADB"); only "protocol only" survived, and
it never showed the menu — so a new entry could only be created on that one
path and the sub-screens were unreachable.
F2 — the menu's rows broke the rule this repo documents: HA dispatches a row
to `async_step_<row id>` AND dispatches a submitted form by its OWN step_id,
so a row named `adb` with a handler called `async_step_adb_pair` is an
UnknownStep, and a row named `receiver` rendering `step_id="setup_receiver"`
is a form that cannot be submitted. The rows are now their handler names
(`receiver`, `connection`, `adb_pair`, `protocol_pair`, `finish`) and the
two sub-screens render their row id. There is also a `_paired_adb` guard
now, so a completed ADB pairing stops offering that row — the rule the
protocol row already followed.
F3 — both menus keyed their row labels under a bare `menu`, which core does
not read (56 core strings files use `menu_options`), so every row fell back
to its raw id in the browser. Renamed in both strings files.
F5 — the per-command script merge is field-wise now: a `script_<command>`
key that is present and empty removes that command, one with a value sets
it, and a key the submission does not carry is untouched — the same rule as
every other option. The wholesale rebuild depended on the page always being
complete, so a partial submission silently wiped the commands it omitted.
THE SYSTEMIC HALF (F1), closed as asked: `ha_api_drift.HA_CALL_OWNERS` now
covers the flow-display APIs (`async_show_menu`, `async_show_progress`,
`async_show_progress_done`, plus the existing form/abort/entry owners), so
the drift engine resolves their REAL signatures and flags an unknown
keyword. `tests/test_ha_api_drift.py` carries a pre-fix source using
`errors=` to prove the new owner is non-vacuous. Every harness stub now
mirrors the real signature (no `errors` on a menu) and a stub-level test
pins that parameter set, so a stub cannot go back to accepting anything.
On the pre-fix tree the drift engine reports exactly this:
config_flow.py:898: unknown-kwarg: async_show_menu() has no 'errors'
parameter; real signature: (self, *, step_id=None, menu_options, sort,
description_placeholders) -> _FlowResultT
TESTS: tests/test_config_flow_real_ha.py gains a SETUP section that drives
the real flow — the first form, the ADB skip, the pairing guard, EVERY menu
row (dispatch AND re-submittable step_id), an accepted sub-screen
submission, a full connection+receiver+finish walk merging into one entry,
the menu's pairing note, and the five-path map as a parametrised test.
11 of those fail on the pre-fix tree; the drift engine failure above is the
12th. The stub suite additionally pins the menu stub's signature and the
`menu_options` key in both strings files.
Also in this commit (t57 F4): the real-HA file claimed entity-valued pages
could not be driven there, which was false (it has always submitted
`switch.soundbar`). The claim is gone and the scripts page is driven through
SET (two scripts selected, real entity ids) → CLEAR (one selector emptied)
→ SAVE → REOPEN, so the SET half is pinned in the real flow and not only
against the selector objects.
This commit is contained in:
1 parent
5eefd0c6d0
commit
3a55519b74
10 files changed
+713
-208
No files matched your search
@@ -44,6 +44,22 @@ PRE_FIX_SOURCES = {
|
||||
" async def async_step_zeroconf(self, discovery_info):\n"
|
||||
" self._async_handle_discovery_without_unique_id()\n"
|
||||
),
|
||||
# t57 UNIT 0a: a wrong kwarg on a FLOW-DISPLAY API. `async_show_menu` takes
|
||||
# no `errors` in HA 2026.10.1, and the integration passed one — so every
|
||||
# ordinary setup path raised TypeError at the moment a user submitted the
|
||||
# first form, which is invisible to a stub suite whose stubs accept it.
|
||||
"t57_show_menu_errors.py": (
|
||||
"from homeassistant import config_entries\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"class PreFixSetupMenu(config_entries.ConfigFlow, domain='nvidia_shield'):\n"
|
||||
" async def async_step_user(self, user_input=None):\n"
|
||||
" return self.async_show_menu(\n"
|
||||
" step_id='menu',\n"
|
||||
" menu_options=['finish'],\n"
|
||||
" errors={\'base\': \'nope\'},\n"
|
||||
" )\n"
|
||||
),
|
||||
"t35_options_updates.py": (
|
||||
"from homeassistant import config_entries\n"
|
||||
"\n"
|
||||
@@ -106,6 +122,7 @@ def test_the_sweep_flags_the_pre_fix_defects(tmp_path):
|
||||
("d2_util_diagnostic.py", "broken-import"),
|
||||
("d3_unawaited_discovery.py", "missing-await"),
|
||||
("t35_options_updates.py", "unknown-kwarg"),
|
||||
("t57_show_menu_errors.py", "unknown-kwarg"),
|
||||
}, "\n" + str(report)
|
||||
|
||||
|
||||
@@ -290,6 +307,12 @@ _REAL_HA_MATRIX = (
|
||||
{"jellyfin_entity": "media_player.jellyfin"},
|
||||
"sensor.shield_now_playing",
|
||||
),
|
||||
(
|
||||
"sensor",
|
||||
"NvidiaShieldAppsSensor",
|
||||
{"adb_enabled": True},
|
||||
"sensor.shield_installed_apps",
|
||||
),
|
||||
("remote", "NvidiaShieldRemoteEntity", None, "remote.shield"),
|
||||
("button", "NvidiaShieldPairAdbButton", None, "button.shield_pair_adb"),
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user