From f31b9eae614873855ba7caa6922201a4b5b07aa1 Mon Sep 17 00:00:00 2001
From: jjlawren <jjlawren@users.noreply.github.com>
Date: Sat, 18 Sep 2021 12:54:54 -0500
Subject: [PATCH] Fix creating `cert_expiry` configs during runtime (#56298)

* Fix creating cert_expiry configs during runtime

* Address review feedback on tests

* Improve delayed startup test
---
 .../components/cert_expiry/__init__.py        | 13 +++++--
 tests/components/cert_expiry/test_init.py     | 39 +++++++++++++++++++
 tests/components/cert_expiry/test_sensors.py  | 21 +++++-----
 3 files changed, 58 insertions(+), 15 deletions(-)

diff --git a/homeassistant/components/cert_expiry/__init__.py b/homeassistant/components/cert_expiry/__init__.py
index 22339b9f4c4..61c7a0758c7 100644
--- a/homeassistant/components/cert_expiry/__init__.py
+++ b/homeassistant/components/cert_expiry/__init__.py
@@ -7,7 +7,7 @@ from typing import Optional
 
 from homeassistant.config_entries import ConfigEntry
 from homeassistant.const import CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STARTED
-from homeassistant.core import HomeAssistant
+from homeassistant.core import CoreState, HomeAssistant
 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
 
 from .const import DEFAULT_PORT, DOMAIN
@@ -38,9 +38,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
         await coordinator.async_refresh()
         hass.config_entries.async_setup_platforms(entry, PLATFORMS)
 
-    entry.async_on_unload(
-        hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, async_finish_startup)
-    )
+    if hass.state == CoreState.running:
+        await async_finish_startup(None)
+    else:
+        entry.async_on_unload(
+            hass.bus.async_listen_once(
+                EVENT_HOMEASSISTANT_STARTED, async_finish_startup
+            )
+        )
 
     return True
 
diff --git a/tests/components/cert_expiry/test_init.py b/tests/components/cert_expiry/test_init.py
index 25771c39250..9bf7512d238 100644
--- a/tests/components/cert_expiry/test_init.py
+++ b/tests/components/cert_expiry/test_init.py
@@ -12,6 +12,7 @@ from homeassistant.const import (
     EVENT_HOMEASSISTANT_STARTED,
     STATE_UNAVAILABLE,
 )
+from homeassistant.core import CoreState
 from homeassistant.setup import async_setup_component
 import homeassistant.util.dt as dt_util
 
@@ -23,6 +24,8 @@ from tests.common import MockConfigEntry, async_fire_time_changed
 
 async def test_setup_with_config(hass):
     """Test setup component with config."""
+    assert hass.state is CoreState.running
+
     config = {
         SENSOR_DOMAIN: [
             {"platform": DOMAIN, CONF_HOST: HOST, CONF_PORT: PORT},
@@ -49,6 +52,8 @@ async def test_setup_with_config(hass):
 
 async def test_update_unique_id(hass):
     """Test updating a config entry without a unique_id."""
+    assert hass.state is CoreState.running
+
     entry = MockConfigEntry(domain=DOMAIN, data={CONF_HOST: HOST, CONF_PORT: PORT})
     entry.add_to_hass(hass)
 
@@ -71,6 +76,8 @@ async def test_update_unique_id(hass):
 @patch("homeassistant.util.dt.utcnow", return_value=static_datetime())
 async def test_unload_config_entry(mock_now, hass):
     """Test unloading a config entry."""
+    assert hass.state is CoreState.running
+
     entry = MockConfigEntry(
         domain=DOMAIN,
         data={CONF_HOST: HOST, CONF_PORT: PORT},
@@ -107,3 +114,35 @@ async def test_unload_config_entry(mock_now, hass):
     await hass.async_block_till_done()
     state = hass.states.get("sensor.cert_expiry_timestamp_example_com")
     assert state is None
+
+
+async def test_delay_load_during_startup(hass):
+    """Test delayed loading of a config entry during startup."""
+    hass.state = CoreState.not_running
+
+    entry = MockConfigEntry(domain=DOMAIN, data={CONF_HOST: HOST, CONF_PORT: PORT})
+    entry.add_to_hass(hass)
+
+    assert await async_setup_component(hass, DOMAIN, {}) is True
+    await hass.async_block_till_done()
+
+    assert hass.state is CoreState.not_running
+    assert entry.state is ConfigEntryState.LOADED
+
+    state = hass.states.get("sensor.cert_expiry_timestamp_example_com")
+    assert state is None
+
+    timestamp = future_timestamp(100)
+    with patch(
+        "homeassistant.components.cert_expiry.get_cert_expiry_timestamp",
+        return_value=timestamp,
+    ):
+        await hass.async_start()
+        await hass.async_block_till_done()
+
+    assert hass.state is CoreState.running
+
+    state = hass.states.get("sensor.cert_expiry_timestamp_example_com")
+    assert state.state == timestamp.isoformat()
+    assert state.attributes.get("error") == "None"
+    assert state.attributes.get("is_valid")
diff --git a/tests/components/cert_expiry/test_sensors.py b/tests/components/cert_expiry/test_sensors.py
index 0ca228dc344..a4456724270 100644
--- a/tests/components/cert_expiry/test_sensors.py
+++ b/tests/components/cert_expiry/test_sensors.py
@@ -5,13 +5,8 @@ import ssl
 from unittest.mock import patch
 
 from homeassistant.components.cert_expiry.const import DOMAIN
-from homeassistant.const import (
-    CONF_HOST,
-    CONF_PORT,
-    EVENT_HOMEASSISTANT_STARTED,
-    STATE_UNAVAILABLE,
-    STATE_UNKNOWN,
-)
+from homeassistant.const import CONF_HOST, CONF_PORT, STATE_UNAVAILABLE, STATE_UNKNOWN
+from homeassistant.core import CoreState
 from homeassistant.util.dt import utcnow
 
 from .const import HOST, PORT
@@ -23,6 +18,8 @@ from tests.common import MockConfigEntry, async_fire_time_changed
 @patch("homeassistant.util.dt.utcnow", return_value=static_datetime())
 async def test_async_setup_entry(mock_now, hass):
     """Test async_setup_entry."""
+    assert hass.state is CoreState.running
+
     entry = MockConfigEntry(
         domain=DOMAIN,
         data={CONF_HOST: HOST, CONF_PORT: PORT},
@@ -37,7 +34,6 @@ async def test_async_setup_entry(mock_now, hass):
     ):
         entry.add_to_hass(hass)
         assert await hass.config_entries.async_setup(entry.entry_id)
-        hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
         await hass.async_block_till_done()
 
     state = hass.states.get("sensor.cert_expiry_timestamp_example_com")
@@ -50,6 +46,8 @@ async def test_async_setup_entry(mock_now, hass):
 
 async def test_async_setup_entry_bad_cert(hass):
     """Test async_setup_entry with a bad/expired cert."""
+    assert hass.state is CoreState.running
+
     entry = MockConfigEntry(
         domain=DOMAIN,
         data={CONF_HOST: HOST, CONF_PORT: PORT},
@@ -62,7 +60,6 @@ async def test_async_setup_entry_bad_cert(hass):
     ):
         entry.add_to_hass(hass)
         assert await hass.config_entries.async_setup(entry.entry_id)
-        hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
         await hass.async_block_till_done()
 
     state = hass.states.get("sensor.cert_expiry_timestamp_example_com")
@@ -74,6 +71,8 @@ async def test_async_setup_entry_bad_cert(hass):
 
 async def test_update_sensor(hass):
     """Test async_update for sensor."""
+    assert hass.state is CoreState.running
+
     entry = MockConfigEntry(
         domain=DOMAIN,
         data={CONF_HOST: HOST, CONF_PORT: PORT},
@@ -89,7 +88,6 @@ async def test_update_sensor(hass):
     ):
         entry.add_to_hass(hass)
         assert await hass.config_entries.async_setup(entry.entry_id)
-        hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
         await hass.async_block_till_done()
 
     state = hass.states.get("sensor.cert_expiry_timestamp_example_com")
@@ -117,6 +115,8 @@ async def test_update_sensor(hass):
 
 async def test_update_sensor_network_errors(hass):
     """Test async_update for sensor."""
+    assert hass.state is CoreState.running
+
     entry = MockConfigEntry(
         domain=DOMAIN,
         data={CONF_HOST: HOST, CONF_PORT: PORT},
@@ -132,7 +132,6 @@ async def test_update_sensor_network_errors(hass):
     ):
         entry.add_to_hass(hass)
         assert await hass.config_entries.async_setup(entry.entry_id)
-        hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
         await hass.async_block_till_done()
 
     state = hass.states.get("sensor.cert_expiry_timestamp_example_com")
-- 
GitLab