text: """Tests for Tomorrow.io init."""
  from datetime import timedelta
  from unittest.mock import patch
  
  from homeassistant.components.climacell.const import CONF_TIMESTEP, DOMAIN as CC_DOMAIN
  from homeassistant.components.tomorrowio.config_flow import (
      _get_config_schema,
      _get_unique_id,
  )
  from homeassistant.components.tomorrowio.const import DOMAIN
  from homeassistant.components.weather import DOMAIN as WEATHER_DOMAIN
  from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_USER
  from homeassistant.const import (
      CONF_API_KEY,
      CONF_API_VERSION,
      CONF_LATITUDE,
      CONF_LOCATION,
      CONF_LONGITUDE,
      CONF_NAME,
  )
  from homeassistant.core import HomeAssistant
  from homeassistant.helpers import device_registry as dr, entity_registry as er
  from homeassistant.util import dt as dt_util
  
  from .const import MIN_CONFIG
  
  from tests.common import MockConfigEntry, async_fire_time_changed
  from tests.components.climacell.const import API_V3_ENTRY_DATA
  
  NEW_NAME = "New Name"
  
  
  async def test_load_and_unload(hass: HomeAssistant) -> None:
      """Test loading and unloading entry."""
      data = _get_config_schema(hass, SOURCE_USER)(MIN_CONFIG)
      data[CONF_NAME] = "test"
      config_entry = MockConfigEntry(
          domain=DOMAIN,
          data=data,
          options={CONF_TIMESTEP: 1},
          unique_id=_get_unique_id(hass, data),
          version=1,
      )
      config_entry.add_to_hass(hass)
      assert await hass.config_entries.async_setup(config_entry.entry_id)
      await hass.async_block_till_done()
      assert len(hass.states.async_entity_ids(WEATHER_DOMAIN)) == 1
  
      assert await hass.config_entries.async_remove(config_entry.entry_id)
      await hass.async_block_till_done()
      assert len(hass.states.async_entity_ids(WEATHER_DOMAIN)) == 0
  
  
  async def test_update_intervals(
      hass: HomeAssistant, tomorrowio_config_entry_update
  ) -> None:
      """Test coordinator update intervals."""
      now = dt_util.utcnow()
      data = _get_config_schema(hass, SOURCE_USER)(MIN_CONFIG)
      data[CONF_NAME] = "test"
      config_entry = MockConfigEntry(
          domain=DOMAIN,
          data=data,
          options={CONF_TIMESTEP: 1},
          unique_id=_get_unique_id(hass, data),
          version=1,
      )
      config_entry.add_to_hass(hass)
      with patch("homeassistant.helpers.update_coordinator.utcnow", return_value=now):
          assert await hass.config_entries.async_setup(config_entry.entry_id)
          await hass.async_block_till_done()
          assert len(tomorrowio_config_entry_update.call_args_list) == 1
  
      tomorrowio_config_entry_update.reset_mock()
  
      # Before the update interval, no updates yet
      future = now + timedelta(minutes=30)
      with patch("homeassistant.helpers.update_coordinator.utcnow", return_value=future):
          async_fire_time_changed(hass, future)
          await hass.async_block_till_done()
          assert len(tomorrowio_config_entry_update.call_args_list) == 0
  
      tomorrowio_config_entry_update.reset_mock()
  
      # On the update interval, we get a new update
      future = now + timedelta(minutes=32)
      with patch("homeassistant.helpers.update_coordinator.utcnow", return_value=future):
          async_fire_time_changed(hass, now + timedelta(minutes=32))
          await hass.async_block_till_done()
          assert len(tomorrowio_config_entry_update.call_args_list) == 1
  
          tomorrowio_config_entry_update.reset_mock()
  
          # Adding a second config entry should cause the update interval to double
          config_entry_2 = MockConfigEntry(
              domain=DOMAIN,
              data=data,
              options={CONF_TIMESTEP: 1},
              unique_id=f"{_get_unique_id(hass, data)}_1",
              version=1,
          )
          config_entry_2.add_to_hass(hass)
          assert await hass.config_entries.async_setup(config_entry_2.entry_id)
          await hass.async_block_till_done()
          assert config_entry.data[CONF_API_KEY] == config_entry_2.data[CONF_API_KEY]
          # We should get an immediate call once the new config entry is setup for a
          # partial update
          assert len(tomorrowio_config_entry_update.call_args_list) == 1
  
      tomorrowio_config_entry_update.reset_mock()
  
      # We should get no new calls on our old interval
      future = now + timedelta(minutes=64)
      with patch("homeassistant.helpers.update_coordinator.utcnow", return_value=future):
          async_fire_time_changed(hass, future)
          await hass.async_block_till_done()
          assert len(tomorrowio_config_entry_update.call_args_list) == 0
  
      tomorrowio_config_entry_update.reset_mock()
  
      # We should get two calls on our new interval, one for each entry
      future = now + timedelta(minutes=96)
      with patch("homeassistant.helpers.update_coordinator.utcnow", return_value=future):
          async_fire_time_changed(hass, future)
          await hass.async_block_till_done()
          assert len(tomorrowio_config_entry_update.call_args_list) == 2
  
      tomorrowio_config_entry_update.reset_mock()
  
  
  async def test_climacell_migration_logic(
      hass: HomeAssistant, climacell_config_entry_update
  ) -> None:
      """Test that climacell config entry is properly migrated."""
      old_data = API_V3_ENTRY_DATA.copy()
      old_data[CONF_API_KEY] = "v3apikey"
      old_config_entry = MockConfigEntry(
          domain=CC_DOMAIN,
          data=old_data,
          unique_id="v3apikey_80.0_80.0",
          version=1,
      )
      old_config_entry.add_to_hass(hass)
      # Let's create a device and update its name
      dev_reg = dr.async_get(hass)
      old_device = dev_reg.async_get_or_create(
          config_entry_id=old_config_entry.entry_id,
          identifiers={(CC_DOMAIN, old_data[CONF_API_KEY])},
          manufacturer="ClimaCell",
          sw_version="v4",
          entry_type="service",
          name="ClimaCell",
      )
      dev_reg.async_update_device(old_device.id, name_by_user=NEW_NAME)
      # Now let's create some entity and update some things to see if everything migrates
      # over
      ent_reg = er.async_get(hass)
      old_entity_daily = ent_reg.async_get_or_create(
          "weather",
          CC_DOMAIN,
          "v3apikey_80.0_80.0_daily",
          config_entry=old_config_entry,
          original_name="ClimaCell - Daily",
          suggested_object_id="climacell_daily",
          device_id=old_device.id,
      )
      old_entity_hourly = ent_reg.async_get_or_create(
          "weather",
          CC_DOMAIN,
          "v3apikey_80.0_80.0_hourly",
          config_entry=old_config_entry,
          original_name="ClimaCell - Hourly",
          suggested_object_id="climacell_hourly",
          device_id=old_device.id,
          disabled_by=er.RegistryEntryDisabler.USER,
      )
      old_entity_nowcast = ent_reg.async_get_or_create(
          "weather",
          CC_DOMAIN,
          "v3apikey_80.0_80.0_nowcast",
          config_entry=old_config_entry,
          original_name="ClimaCell - Nowcast",
          suggested_object_id="climacell_nowcast",
          device_id=old_device.id,
      )
      ent_reg.async_update_entity(old_entity_daily.entity_id, name=NEW_NAME)
  
      # Now let's create a new tomorrowio config entry that is supposedly created from a
      # climacell import and see what happens - we are also changing the API key to ensure
      # that things work as expected
      new_data = API_V3_ENTRY_DATA.copy()
      new_data[CONF_LOCATION] = {
          CONF_LATITUDE: float(new_data.pop(CONF_LATITUDE)),
          CONF_LONGITUDE: float(new_data.pop(CONF_LONGITUDE)),
      }
      new_data[CONF_API_VERSION] = 4
      new_data["old_config_entry_id"] = old_config_entry.entry_id
      config_entry = MockConfigEntry(
          domain=DOMAIN,
          data=new_data,
          unique_id=_get_unique_id(hass, new_data),
          version=1,
          source=SOURCE_IMPORT,
      )
      config_entry.add_to_hass(hass)
      await hass.config_entries.async_setup(config_entry.entry_id)
      await hass.async_block_till_done()
  
      # Check that the old device no longer exists
      assert dev_reg.async_get(old_device.id) is None
  
      # Check that the new device was created and that it has the correct name
      assert (
          dr.async_entries_for_config_entry(dev_reg, config_entry.entry_id)[
              0
          ].name_by_user
          == NEW_NAME
      )
  
      # Check that the new entities match the old ones (minus the default name)
      new_entity_daily = ent_reg.async_get(old_entity_daily.entity_id)
      assert new_entity_daily.platform == DOMAIN
      assert new_entity_daily.name == NEW_NAME
      assert new_entity_daily.original_name == "ClimaCell - Daily"
      assert new_entity_daily.device_id != old_device.id
      assert new_entity_daily.unique_id == f"{_get_unique_id(hass, new_data)}_daily"
      assert new_entity_daily.disabled_by is None
  
      new_entity_hourly = ent_reg.async_get(old_entity_hourly.entity_id)
      assert new_entity_hourly.platform == DOMAIN
      assert new_entity_hourly.name is None
      assert new_entity_hourly.original_name == "ClimaCell - Hourly"
      assert new_entity_hourly.device_id != old_device.id
      assert new_entity_hourly.unique_id == f"{_get_unique_id(hass, new_data)}_hourly"
      assert new_entity_hourly.disabled_by == er.RegistryEntryDisabler.USER
  
      new_entity_nowcast = ent_reg.async_get(old_entity_nowcast.entity_id)
      assert new_entity_nowcast.platform == DOMAIN
      assert new_entity_nowcast.name is None
      assert new_entity_nowcast.original_name == "ClimaCell - Nowcast"
      assert new_entity_nowcast.device_id != old_device.id
      assert new_entity_nowcast.unique_id == f"{_get_unique_id(hass, new_data)}_nowcast"
      assert new_entity_nowcast.disabled_by is None
  