fix(config_flow): F2 — MAC-less zeroconf discovery calls the audited _async_handle_discovery_without_unique_id helper and guards against a same-host duplicate prefill, so re-discovery can't stack entries; the import guard reads entries via the base _async_current_entries helper; TestMacLessDiscoveryF2 pins helper call + one-entry outcome (t32)
This commit is contained in:
1 parent
8f40b6435c
commit
6087566336
4 files changed
+72
-2
No files matched your search
@@ -95,6 +95,12 @@ def _install_stubs() -> None:
|
||||
def _async_current_entries(self):
|
||||
return _zc_holder.entries
|
||||
|
||||
# t32 F2: the audited helper for uniqueness-less discovery — a
|
||||
# recording no-op here; the flow's own host guard does the stacking
|
||||
# prevention the acceptance pins.
|
||||
def _async_handle_discovery_without_unique_id(self):
|
||||
_zc_holder.discovery_without_unique_id_calls += 1
|
||||
|
||||
class OptionsFlow:
|
||||
def async_show_form(self, *, step_id, data_schema=None, errors=None):
|
||||
return {
|
||||
@@ -128,7 +134,7 @@ def _install_stubs() -> None:
|
||||
|
||||
# Shared holder so tests can swap the current-entry list through the
|
||||
# module object (the stub closure reads this same object).
|
||||
_zc_holder = types.SimpleNamespace(entries=[])
|
||||
_zc_holder = types.SimpleNamespace(entries=[], discovery_without_unique_id_calls=0)
|
||||
sys.modules[__name__]._zc_holder = _zc_holder
|
||||
|
||||
class AbortIfConfiguredError(Exception):
|
||||
@@ -835,6 +841,50 @@ class TestIpChangeSelfHealF1:
|
||||
assert factory() is None
|
||||
|
||||
|
||||
class TestMacLessDiscoveryF2:
|
||||
"""t32 F2 (rider): MAC-less zeroconf discovery records the
|
||||
uniqueness-less discovery and can't stack a duplicate prefill."""
|
||||
|
||||
def _discovery(self, host="192.168.1.50", props=None):
|
||||
return SimpleNamespace(
|
||||
ip_address=host, host=host, properties=props or {}
|
||||
)
|
||||
|
||||
async def test_mac_less_records_the_helper(self, tmp_path):
|
||||
module = _form_module()
|
||||
flow = module.NvidiaShieldConfigFlow()
|
||||
flow.hass = FakeHass(str(tmp_path))
|
||||
sys.modules[__name__]._zc_holder.discovery_without_unique_id_calls = 0
|
||||
|
||||
result = await flow.async_step_zeroconf(self._discovery())
|
||||
|
||||
assert result["type"] == "form" # prefill still offered once
|
||||
assert (
|
||||
sys.modules[__name__]._zc_holder.discovery_without_unique_id_calls
|
||||
== 1
|
||||
)
|
||||
|
||||
async def test_mac_less_rediscovery_does_not_stack(self, tmp_path):
|
||||
"""A second MAC-less discovery of an already-configured host
|
||||
aborts — one-entry outcome."""
|
||||
module = _form_module()
|
||||
flow = module.NvidiaShieldConfigFlow()
|
||||
flow.hass = FakeHass(str(tmp_path))
|
||||
entry = SimpleNamespace(
|
||||
entry_id="e1",
|
||||
unique_id=None, # MAC-less entry
|
||||
options={CONF_PROTOCOL_HOST: "192.168.1.50"},
|
||||
title="Shield",
|
||||
)
|
||||
sys.modules[__name__]._zc_holder.entries[:] = [entry]
|
||||
|
||||
result = await flow.async_step_zeroconf(self._discovery())
|
||||
|
||||
assert result == {"type": "abort", "reason": "already_configured"}
|
||||
# the entries list is untouched: one-entry outcome
|
||||
assert len(sys.modules[__name__]._zc_holder.entries) == 1
|
||||
|
||||
|
||||
class TestZeroconfDiscovery:
|
||||
"""P4-1a: _androidtvremote2._tcp discovery → pre-filled user step."""
|
||||
|
||||
|
||||
Reference in new issue
Block a user