diff --git a/homeassistant/components/brother/config_flow.py b/homeassistant/components/brother/config_flow.py index 8966b41c948e23..ffc2b3bfa8ac80 100644 --- a/homeassistant/components/brother/config_flow.py +++ b/homeassistant/components/brother/config_flow.py @@ -9,7 +9,7 @@ from homeassistant.components import zeroconf from homeassistant.components.snmp import async_get_snmp_engine -from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult +from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.const import CONF_HOST, CONF_TYPE from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError @@ -49,8 +49,6 @@ class BrotherConfigFlow(ConfigFlow, domain=DOMAIN): VERSION = 1 - entry: ConfigEntry - def __init__(self) -> None: """Initialize.""" self.brother: Brother @@ -145,18 +143,18 @@ async def async_step_reconfigure( self, user_input: dict[str, Any] | None = None ) -> ConfigFlowResult: """Handle a reconfiguration flow initialized by the user.""" - self.entry = self._get_reconfigure_entry() return await self.async_step_reconfigure_confirm() async def async_step_reconfigure_confirm( self, user_input: dict[str, Any] | None = None ) -> ConfigFlowResult: """Handle a reconfiguration flow initialized by the user.""" + entry = self._get_reconfigure_entry() errors = {} if user_input is not None: try: - await validate_input(self.hass, user_input, self.entry.unique_id) + await validate_input(self.hass, user_input, entry.unique_id) except InvalidHost: errors[CONF_HOST] = "wrong_host" except (ConnectionError, TimeoutError): @@ -166,20 +164,18 @@ async def async_step_reconfigure_confirm( except AnotherDevice: errors["base"] = "another_device" else: - self.hass.config_entries.async_update_entry( - self.entry, - data=self.entry.data | {CONF_HOST: user_input[CONF_HOST]}, + return self.async_update_reload_and_abort( + entry, + data_updates={CONF_HOST: user_input[CONF_HOST]}, ) - await self.hass.config_entries.async_reload(self.entry.entry_id) - return self.async_abort(reason="reconfigure_successful") return self.async_show_form( step_id="reconfigure_confirm", data_schema=self.add_suggested_values_to_schema( data_schema=RECONFIGURE_SCHEMA, - suggested_values=self.entry.data | (user_input or {}), + suggested_values=entry.data | (user_input or {}), ), - description_placeholders={"printer_name": self.entry.title}, + description_placeholders={"printer_name": entry.title}, errors=errors, ) diff --git a/homeassistant/components/habitica/__init__.py b/homeassistant/components/habitica/__init__.py index 8781a6e2d48b54..0f5b9bd2b50a55 100644 --- a/homeassistant/components/habitica/__init__.py +++ b/homeassistant/components/habitica/__init__.py @@ -8,13 +8,11 @@ from habitipy.aio import HabitipyAsync import voluptuous as vol -from homeassistant import config_entries from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( ATTR_NAME, CONF_API_KEY, CONF_NAME, - CONF_SENSORS, CONF_URL, CONF_VERIFY_SSL, Platform, @@ -43,7 +41,6 @@ ATTR_SKILL, ATTR_TASK, CONF_API_USER, - DEFAULT_URL, DOMAIN, EVENT_API_CALL_SUCCESS, SERVICE_API_CALL, @@ -52,54 +49,14 @@ from .coordinator import HabiticaDataUpdateCoordinator _LOGGER = logging.getLogger(__name__) +CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) type HabiticaConfigEntry = ConfigEntry[HabiticaDataUpdateCoordinator] -SENSORS_TYPES = ["name", "hp", "maxHealth", "mp", "maxMP", "exp", "toNextLevel", "lvl"] - -INSTANCE_SCHEMA = vol.All( - cv.deprecated(CONF_SENSORS), - vol.Schema( - { - vol.Optional(CONF_URL, default=DEFAULT_URL): cv.url, - vol.Optional(CONF_NAME): cv.string, - vol.Required(CONF_API_USER): cv.string, - vol.Required(CONF_API_KEY): cv.string, - vol.Optional(CONF_SENSORS, default=list(SENSORS_TYPES)): vol.All( - cv.ensure_list, vol.Unique(), [vol.In(list(SENSORS_TYPES))] - ), - } - ), -) - -has_unique_values = vol.Schema(vol.Unique()) -# because we want a handy alias - - -def has_all_unique_users(value): - """Validate that all API users are unique.""" - api_users = [user[CONF_API_USER] for user in value] - has_unique_values(api_users) - return value - - -def has_all_unique_users_names(value): - """Validate that all user's names are unique and set if any is set.""" - names = [user.get(CONF_NAME) for user in value] - if None in names and any(name is not None for name in names): - raise vol.Invalid("user names of all users must be set if any is set") - if not all(name is None for name in names): - has_unique_values(names) - return value - - -INSTANCE_LIST_SCHEMA = vol.All( - cv.ensure_list, has_all_unique_users, has_all_unique_users_names, [INSTANCE_SCHEMA] -) -CONFIG_SCHEMA = vol.Schema({DOMAIN: INSTANCE_LIST_SCHEMA}, extra=vol.ALLOW_EXTRA) PLATFORMS = [Platform.BUTTON, Platform.SENSOR, Platform.SWITCH, Platform.TODO] + SERVICE_API_CALL_SCHEMA = vol.Schema( { vol.Required(ATTR_NAME): str, @@ -118,17 +75,6 @@ def has_all_unique_users_names(value): async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the Habitica service.""" - configs = config.get(DOMAIN, []) - - for conf in configs: - if conf.get(CONF_URL) is None: - conf[CONF_URL] = DEFAULT_URL - - hass.async_create_task( - hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data=conf - ) - ) async def cast_skill(call: ServiceCall) -> ServiceResponse: """Skill action.""" diff --git a/homeassistant/components/habitica/config_flow.py b/homeassistant/components/habitica/config_flow.py index 2947032c41ef76..88f3d1b803c8ed 100644 --- a/homeassistant/components/habitica/config_flow.py +++ b/homeassistant/components/habitica/config_flow.py @@ -18,9 +18,7 @@ CONF_USERNAME, CONF_VERIFY_SSL, ) -from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN from homeassistant.helpers.aiohttp_client import async_get_clientsession -from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue from homeassistant.helpers.selector import ( TextSelector, TextSelectorConfig, @@ -178,21 +176,3 @@ async def async_step_advanced( ), errors=errors, ) - - async def async_step_import(self, import_data: dict[str, Any]) -> ConfigFlowResult: - """Import habitica config from configuration.yaml.""" - - async_create_issue( - self.hass, - HOMEASSISTANT_DOMAIN, - f"deprecated_yaml_{DOMAIN}", - is_fixable=False, - breaks_in_ha_version="2024.11.0", - severity=IssueSeverity.WARNING, - translation_key="deprecated_yaml", - translation_placeholders={ - "domain": DOMAIN, - "integration_title": "Habitica", - }, - ) - return await self.async_step_advanced(import_data) diff --git a/tests/components/habitica/test_config_flow.py b/tests/components/habitica/test_config_flow.py index 09cda3fbb0a005..604877f0c47a0b 100644 --- a/tests/components/habitica/test_config_flow.py +++ b/tests/components/habitica/test_config_flow.py @@ -17,8 +17,6 @@ from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType -from tests.common import MockConfigEntry - MOCK_DATA_LOGIN_STEP = { CONF_USERNAME: "test-email@example.com", CONF_PASSWORD: "test-password", @@ -217,38 +215,3 @@ async def test_form_advanced_errors( assert result2["type"] is FlowResultType.FORM assert result2["errors"] == {"base": text_error} - - -async def test_manual_flow_config_exist(hass: HomeAssistant) -> None: - """Test config flow discovers only already configured config.""" - MockConfigEntry( - domain=DOMAIN, - unique_id="test-api-user", - data={"api_user": "test-api-user", "api_key": "test-api-key"}, - ).add_to_hass(hass) - - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_IMPORT} - ) - - assert result["type"] is FlowResultType.FORM - assert result["step_id"] == "advanced" - - mock_obj = MagicMock() - mock_obj.user.get = AsyncMock(return_value={"api_user": "test-api-user"}) - - with patch( - "homeassistant.components.habitica.config_flow.HabitipyAsync", - return_value=mock_obj, - ): - result = await hass.config_entries.flow.async_configure( - result["flow_id"], - { - "url": DEFAULT_URL, - "api_user": "test-api-user", - "api_key": "test-api-key", - }, - ) - - assert result["type"] is FlowResultType.ABORT - assert result["reason"] == "already_configured" diff --git a/tests/components/workday/snapshots/test_binary_sensor.ambr b/tests/components/workday/snapshots/test_binary_sensor.ambr index 8ad2f37f360384..4cf7dca48612bb 100644 --- a/tests/components/workday/snapshots/test_binary_sensor.ambr +++ b/tests/components/workday/snapshots/test_binary_sensor.ambr @@ -5,21 +5,55 @@ 'workday', 'bad_date_holiday-1-2024_08_15', ): IssueRegistryItemSnapshot({ + 'active': True, + 'breaks_in_ha_version': None, 'created': , + 'data': dict({ + 'country': 'DE', + 'entry_id': '1', + 'named_holiday': '2024-08-15', + }), 'dismissed_version': None, 'domain': 'workday', + 'is_fixable': True, 'is_persistent': False, + 'issue_domain': None, 'issue_id': 'bad_date_holiday-1-2024_08_15', + 'learn_more_url': None, + 'severity': , + 'translation_key': 'bad_date_holiday', + 'translation_placeholders': dict({ + 'country': 'DE', + 'remove_holidays': '2024-08-15', + 'title': 'Mock Title', + }), }), tuple( 'workday', 'bad_date_holiday-1-2025_08_15', ): IssueRegistryItemSnapshot({ + 'active': True, + 'breaks_in_ha_version': None, 'created': , + 'data': dict({ + 'country': 'DE', + 'entry_id': '1', + 'named_holiday': '2025-08-15', + }), 'dismissed_version': None, 'domain': 'workday', + 'is_fixable': True, 'is_persistent': False, + 'issue_domain': None, 'issue_id': 'bad_date_holiday-1-2025_08_15', + 'learn_more_url': None, + 'severity': , + 'translation_key': 'bad_date_holiday', + 'translation_placeholders': dict({ + 'country': 'DE', + 'remove_holidays': '2025-08-15', + 'title': 'Mock Title', + }), }), }) # --- diff --git a/tests/syrupy.py b/tests/syrupy.py index b6f753e6c7f908..268ee59243f0ee 100644 --- a/tests/syrupy.py +++ b/tests/syrupy.py @@ -197,7 +197,7 @@ def _serializable_issue_registry_entry( cls, data: ir.IssueEntry ) -> SerializableData: """Prepare a Home Assistant issue registry entry for serialization.""" - return IssueRegistryItemSnapshot(data.to_json() | {"created": ANY}) + return IssueRegistryItemSnapshot(dataclasses.asdict(data) | {"created": ANY}) @classmethod def _serializable_state(cls, data: State) -> SerializableData: