From bc45b31335d6e05caf662354ca7cb61ae2846f08 Mon Sep 17 00:00:00 2001 From: G Johansson Date: Sun, 4 Feb 2024 15:15:17 -0500 Subject: [PATCH] Fix repairs for remove dates in Workday (#109626) --- .../components/workday/binary_sensor.py | 62 ++++++++----- homeassistant/components/workday/repairs.py | 6 +- homeassistant/components/workday/strings.json | 22 ++++- tests/components/workday/__init__.py | 11 +++ tests/components/workday/test_repairs.py | 89 ++++++++++++++++++- 5 files changed, 163 insertions(+), 27 deletions(-) diff --git a/homeassistant/components/workday/binary_sensor.py b/homeassistant/components/workday/binary_sensor.py index bda3a576563..04a3a2544c1 100644 --- a/homeassistant/components/workday/binary_sensor.py +++ b/homeassistant/components/workday/binary_sensor.py @@ -1,4 +1,5 @@ """Sensor to indicate whether the current day is a workday.""" + from __future__ import annotations from datetime import date, timedelta @@ -53,7 +54,7 @@ def validate_dates(holiday_list: list[str]) -> list[str]: continue _range: timedelta = d2 - d1 for i in range(_range.days + 1): - day = d1 + timedelta(days=i) + day: date = d1 + timedelta(days=i) calc_holidays.append(day.strftime("%Y-%m-%d")) continue calc_holidays.append(add_date) @@ -123,25 +124,46 @@ async def async_setup_entry( LOGGER.debug("Removed %s by name '%s'", holiday, remove_holiday) except KeyError as unmatched: LOGGER.warning("No holiday found matching %s", unmatched) - async_create_issue( - hass, - DOMAIN, - f"bad_named_holiday-{entry.entry_id}-{slugify(remove_holiday)}", - is_fixable=True, - is_persistent=False, - severity=IssueSeverity.WARNING, - translation_key="bad_named_holiday", - translation_placeholders={ - CONF_COUNTRY: country if country else "-", - "title": entry.title, - CONF_REMOVE_HOLIDAYS: remove_holiday, - }, - data={ - "entry_id": entry.entry_id, - "country": country, - "named_holiday": remove_holiday, - }, - ) + if dt_util.parse_date(remove_holiday): + async_create_issue( + hass, + DOMAIN, + f"bad_date_holiday-{entry.entry_id}-{slugify(remove_holiday)}", + is_fixable=True, + is_persistent=False, + severity=IssueSeverity.WARNING, + translation_key="bad_date_holiday", + translation_placeholders={ + CONF_COUNTRY: country if country else "-", + "title": entry.title, + CONF_REMOVE_HOLIDAYS: remove_holiday, + }, + data={ + "entry_id": entry.entry_id, + "country": country, + "named_holiday": remove_holiday, + }, + ) + else: + async_create_issue( + hass, + DOMAIN, + f"bad_named_holiday-{entry.entry_id}-{slugify(remove_holiday)}", + is_fixable=True, + is_persistent=False, + severity=IssueSeverity.WARNING, + translation_key="bad_named_holiday", + translation_placeholders={ + CONF_COUNTRY: country if country else "-", + "title": entry.title, + CONF_REMOVE_HOLIDAYS: remove_holiday, + }, + data={ + "entry_id": entry.entry_id, + "country": country, + "named_holiday": remove_holiday, + }, + ) LOGGER.debug("Found the following holidays for your configuration:") for holiday_date, name in sorted(obj_holidays.items()): diff --git a/homeassistant/components/workday/repairs.py b/homeassistant/components/workday/repairs.py index 905434f76ac..1221514da42 100644 --- a/homeassistant/components/workday/repairs.py +++ b/homeassistant/components/workday/repairs.py @@ -125,9 +125,9 @@ class HolidayFixFlow(RepairsFlow): self, user_input: dict[str, str] | None = None ) -> data_entry_flow.FlowResult: """Handle the first step of a fix flow.""" - return await self.async_step_named_holiday() + return await self.async_step_fix_remove_holiday() - async def async_step_named_holiday( + async def async_step_fix_remove_holiday( self, user_input: dict[str, Any] | None = None ) -> data_entry_flow.FlowResult: """Handle the options step of a fix flow.""" @@ -168,7 +168,7 @@ class HolidayFixFlow(RepairsFlow): {CONF_REMOVE_HOLIDAYS: removed_named_holiday}, ) return self.async_show_form( - step_id="named_holiday", + step_id="fix_remove_holiday", data_schema=new_schema, description_placeholders={ CONF_COUNTRY: self.country if self.country else "-", diff --git a/homeassistant/components/workday/strings.json b/homeassistant/components/workday/strings.json index bbb76676f96..0e618beaf82 100644 --- a/homeassistant/components/workday/strings.json +++ b/homeassistant/components/workday/strings.json @@ -137,7 +137,7 @@ "title": "Configured named holiday {remove_holidays} for {title} does not exist", "fix_flow": { "step": { - "named_holiday": { + "fix_remove_holiday": { "title": "[%key:component::workday::issues::bad_named_holiday::title%]", "description": "Remove named holiday `{remove_holidays}` as it can't be found in country {country}.", "data": { @@ -152,6 +152,26 @@ "remove_holiday_error": "[%key:component::workday::config::error::remove_holiday_error%]" } } + }, + "bad_date_holiday": { + "title": "Configured holiday date {remove_holidays} for {title} does not exist", + "fix_flow": { + "step": { + "fix_remove_holiday": { + "title": "[%key:component::workday::issues::bad_date_holiday::title%]", + "description": "Remove holiday date `{remove_holidays}` as it can't be found in country {country}.", + "data": { + "remove_holidays": "[%key:component::workday::config::step::options::data::remove_holidays%]" + }, + "data_description": { + "remove_holidays": "[%key:component::workday::config::step::options::data_description::remove_holidays%]" + } + } + }, + "error": { + "remove_holiday_error": "[%key:component::workday::config::error::remove_holiday_error%]" + } + } } }, "entity": { diff --git a/tests/components/workday/__init__.py b/tests/components/workday/__init__.py index fb436a57e5c..a7e26765643 100644 --- a/tests/components/workday/__init__.py +++ b/tests/components/workday/__init__.py @@ -1,4 +1,5 @@ """Tests the Home Assistant workday binary sensor.""" + from __future__ import annotations from typing import Any @@ -181,6 +182,16 @@ TEST_CONFIG_REMOVE_NAMED = { "remove_holidays": ["Not a Holiday", "Christmas", "Thanksgiving"], "language": "en_US", } +TEST_CONFIG_REMOVE_DATE = { + "name": DEFAULT_NAME, + "country": "US", + "excludes": DEFAULT_EXCLUDES, + "days_offset": DEFAULT_OFFSET, + "workdays": DEFAULT_WORKDAYS, + "add_holidays": [], + "remove_holidays": ["2024-02-05", "2024-02-06"], + "language": "en_US", +} TEST_CONFIG_TOMORROW = { "name": DEFAULT_NAME, "country": "DE", diff --git a/tests/components/workday/test_repairs.py b/tests/components/workday/test_repairs.py index fc7bfeb1b0e..60a55e1a347 100644 --- a/tests/components/workday/test_repairs.py +++ b/tests/components/workday/test_repairs.py @@ -1,4 +1,5 @@ """Test repairs for unifiprotect.""" + from __future__ import annotations from http import HTTPStatus @@ -10,12 +11,13 @@ from homeassistant.components.repairs.websocket_api import ( from homeassistant.components.workday.const import CONF_REMOVE_HOLIDAYS, DOMAIN from homeassistant.const import CONF_COUNTRY from homeassistant.core import HomeAssistant -from homeassistant.helpers.issue_registry import async_create_issue +from homeassistant.helpers import issue_registry as ir from homeassistant.setup import async_setup_component from . import ( TEST_CONFIG_INCORRECT_COUNTRY, TEST_CONFIG_INCORRECT_PROVINCE, + TEST_CONFIG_REMOVE_DATE, TEST_CONFIG_REMOVE_NAMED, init_integration, ) @@ -329,6 +331,7 @@ async def test_bad_named_holiday( hass: HomeAssistant, hass_client: ClientSessionGenerator, hass_ws_client: WebSocketGenerator, + issue_registry: ir.IssueRegistry, ) -> None: """Test fixing bad province selecting none.""" assert await async_setup_component(hass, "repairs", {}) @@ -337,6 +340,11 @@ async def test_bad_named_holiday( state = hass.states.get("binary_sensor.workday_sensor") assert state + issues = issue_registry.issues.keys() + for issue in issues: + if issue[0] == DOMAIN: + assert issue[1].startswith("bad_named") + ws_client = await hass_ws_client(hass) client = await hass_client() @@ -365,7 +373,7 @@ async def test_bad_named_holiday( CONF_REMOVE_HOLIDAYS: "Not a Holiday", "title": entry.title, } - assert data["step_id"] == "named_holiday" + assert data["step_id"] == "fix_remove_holiday" url = RepairsFlowResourceView.url.format(flow_id=flow_id) resp = await client.post( @@ -402,6 +410,81 @@ async def test_bad_named_holiday( assert not issue +async def test_bad_date_holiday( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + hass_ws_client: WebSocketGenerator, + issue_registry: ir.IssueRegistry, +) -> None: + """Test fixing bad province selecting none.""" + assert await async_setup_component(hass, "repairs", {}) + entry = await init_integration(hass, TEST_CONFIG_REMOVE_DATE) + + state = hass.states.get("binary_sensor.workday_sensor") + assert state + + issues = issue_registry.issues.keys() + for issue in issues: + if issue[0] == DOMAIN: + assert issue[1].startswith("bad_date") + + ws_client = await hass_ws_client(hass) + client = await hass_client() + + await ws_client.send_json({"id": 1, "type": "repairs/list_issues"}) + msg = await ws_client.receive_json() + + assert msg["success"] + assert len(msg["result"]["issues"]) > 0 + issue = None + for i in msg["result"]["issues"]: + if i["issue_id"] == "bad_date_holiday-1-2024_02_05": + issue = i + assert issue is not None + + url = RepairsFlowIndexView.url + resp = await client.post( + url, + json={"handler": DOMAIN, "issue_id": "bad_date_holiday-1-2024_02_05"}, + ) + assert resp.status == HTTPStatus.OK + data = await resp.json() + + flow_id = data["flow_id"] + assert data["description_placeholders"] == { + CONF_COUNTRY: "US", + CONF_REMOVE_HOLIDAYS: "2024-02-05", + "title": entry.title, + } + assert data["step_id"] == "fix_remove_holiday" + + url = RepairsFlowResourceView.url.format(flow_id=flow_id) + resp = await client.post(url, json={"remove_holidays": ["2024-02-06"]}) + assert resp.status == HTTPStatus.OK + data = await resp.json() + + assert data["type"] == "create_entry" + await hass.async_block_till_done() + + state = hass.states.get("binary_sensor.workday_sensor") + assert state + + await ws_client.send_json({"id": 2, "type": "repairs/list_issues"}) + msg = await ws_client.receive_json() + + assert msg["success"] + issue = None + for i in msg["result"]["issues"]: + if i["issue_id"] == "bad_date_holiday-1-2024_02_05": + issue = i + assert not issue + issue = None + for i in msg["result"]["issues"]: + if i["issue_id"] == "bad_date_holiday-1-2024_02_06": + issue = i + assert issue + + async def test_other_fixable_issues( hass: HomeAssistant, hass_client: ClientSessionGenerator, @@ -428,7 +511,7 @@ async def test_other_fixable_issues( "severity": "error", "translation_key": "issue_1", } - async_create_issue( + ir.async_create_issue( hass, issue["domain"], issue["issue_id"],