diff --git a/tests/entity_stublib.py b/tests/entity_stublib.py index 4790c9c..7c795ce 100644 --- a/tests/entity_stublib.py +++ b/tests/entity_stublib.py @@ -131,8 +131,38 @@ def install() -> None: config_entries = types.ModuleType("homeassistant.config_entries") config_entries.ConfigEntry = type("ConfigEntry", (), {}) + async def _stub_set_unique_id(self, unique_id): + # hub shape: record; a full flow test file scopes its own version + self._unique_id = unique_id + + def _noop_abort(self, *, error=None, **kwargs): + return None + class _ConfigFlowStub: - """ConfigFlow shape used by flow tests (t29 G3a API included).""" + """ConfigFlow shape used by entity tests (t29 G3a API included). + + Late loads under the hub stubs (e.g. test_init designs run AFTER the + other flow files) still get the base plumbing the flow modules rely + on — show/create/abort/unique-id — so the flow classes never import + against a bare base. + """ + + async_set_unique_id = _stub_set_unique_id + _abort_if_unique_id_configured = _noop_abort + + def async_show_form(self, *, step_id, data_schema=None, errors=None): + return { + "type": "form", + "step_id": step_id, + "errors": dict(errors or {}), + "data_schema": data_schema, + } + + def async_create_entry(self, *, title, data, options=None): + return {"type": "create_entry", "title": title, "data": data} + + def async_abort(self, *, reason): + return {"type": "abort", "reason": reason} def _get_reauth_entry(self, entry=None): if entry is not None: diff --git a/tests/test_standalone_setup.py b/tests/test_standalone_setup.py index 728b953..1609e66 100644 --- a/tests/test_standalone_setup.py +++ b/tests/test_standalone_setup.py @@ -37,8 +37,15 @@ _STUB_NAMES = ( def _install_stubs() -> None: - """Import-time stand-ins (idempotent; same shape as the pairing tests).""" - if sys.modules.get("voluptuous") is not None: + """Import-time stand-ins (idempotent; same shape as the pairing tests). + + t30: the guard rebuilds whenever the module-level holder is missing — + a later file's scoped teardown may pop the shared stubs this file's + tests rely on (the flow-class surfaces live on the local base which we + MUST rebind against).""" + if sys.modules.get("voluptuous") is not None and hasattr( + sys.modules.get(__name__), "_zc_holder" + ): return vol = types.ModuleType("voluptuous")