diff --git a/homeassistant/components/sun/__init__.py b/homeassistant/components/sun/__init__.py index c619607d5b27..94758d4e99f7 100644 --- a/homeassistant/components/sun/__init__.py +++ b/homeassistant/components/sun/__init__.py @@ -130,9 +130,12 @@ class Sun(Entity): self._config_listener = self.hass.bus.async_listen( EVENT_CORE_CONFIG_UPDATE, self.update_location ) - self._loaded_listener = self.hass.bus.async_listen( - EVENT_COMPONENT_LOADED, self.loading_complete - ) + if DOMAIN in hass.config.components: + self.update_location() + else: + self._loaded_listener = self.hass.bus.async_listen( + EVENT_COMPONENT_LOADED, self.loading_complete + ) @callback def loading_complete(self, event_: Event) -> None: @@ -158,6 +161,7 @@ class Sun(Entity): """Remove the loaded listener.""" if self._loaded_listener: self._loaded_listener() + self._loaded_listener = None @callback def remove_listeners(self): diff --git a/tests/test_config_entries.py b/tests/test_config_entries.py index b62e9bffbce4..2c3092427dcc 100644 --- a/tests/test_config_entries.py +++ b/tests/test_config_entries.py @@ -8,8 +8,12 @@ import pytest from homeassistant import config_entries, data_entry_flow, loader from homeassistant.components.hassio import HassioServiceInfo -from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP -from homeassistant.core import CoreState, callback +from homeassistant.const import ( + EVENT_COMPONENT_LOADED, + EVENT_HOMEASSISTANT_STARTED, + EVENT_HOMEASSISTANT_STOP, +) +from homeassistant.core import CoreState, Event, callback from homeassistant.data_entry_flow import RESULT_TYPE_ABORT, BaseServiceInfo from homeassistant.exceptions import ( ConfigEntryAuthFailed, @@ -2299,6 +2303,72 @@ async def test_async_setup_init_entry(hass): assert entries[0].state is config_entries.ConfigEntryState.LOADED +async def test_async_setup_init_entry_completes_before_loaded_event_fires(hass): + """Test a config entry being initialized during integration setup before the loaded event fires.""" + + @callback + def _record_load(event: Event) -> None: + nonlocal load_events + load_events.append(event) + + listener = hass.bus.async_listen(EVENT_COMPONENT_LOADED, _record_load) + load_events: list[Event] = [] + + async def mock_async_setup(hass, config): + """Mock setup.""" + hass.async_create_task( + hass.config_entries.flow.async_init( + "comp", + context={"source": config_entries.SOURCE_IMPORT}, + data={}, + ) + ) + return True + + async_setup_entry = AsyncMock(return_value=True) + mock_integration( + hass, + MockModule( + "comp", async_setup=mock_async_setup, async_setup_entry=async_setup_entry + ), + ) + mock_entity_platform(hass, "config_flow.comp", None) + + class TestFlow(config_entries.ConfigFlow): + """Test flow.""" + + VERSION = 1 + + async def async_step_three(self, user_input=None): + """Test import step creating entry.""" + return self.async_create_entry(title="title", data={}) + + async def async_step_two(self, user_input=None): + """Test import step creating entry.""" + return await self.async_step_three() + + async def async_step_one(self, user_input=None): + """Test import step creating entry.""" + return await self.async_step_two() + + async def async_step_import(self, user_input=None): + """Test import step creating entry.""" + return await self.async_step_one() + + # This test must not use hass.async_block_till_done() + # as its explicitly testing what happens without it + with patch.dict(config_entries.HANDLERS, {"comp": TestFlow}): + assert await async_setup_component(hass, "comp", {}) + assert len(async_setup_entry.mock_calls) == 1 + assert load_events[0].event_type == EVENT_COMPONENT_LOADED + assert load_events[0].data == {"component": "comp"} + entries = hass.config_entries.async_entries("comp") + assert len(entries) == 1 + assert entries[0].state is config_entries.ConfigEntryState.LOADED + + listener() + + async def test_async_setup_update_entry(hass): """Test a config entry being updated during integration setup.""" entry = MockConfigEntry(domain="comp", data={"value": "initial"})