diff --git a/homeassistant/components/habitica/const.py b/homeassistant/components/habitica/const.py index c33edc0161d7cbf399f76452f9ee85fd0d73b608..cf9d08c160ca78a53946ca4b6ac00144094de955 100644 --- a/homeassistant/components/habitica/const.py +++ b/homeassistant/components/habitica/const.py @@ -72,6 +72,7 @@ SERVICE_CREATE_REWARD = "create_reward" SERVICE_UPDATE_HABIT = "update_habit" SERVICE_CREATE_HABIT = "create_habit" SERVICE_UPDATE_TODO = "update_todo" +SERVICE_CREATE_TODO = "create_todo" DEVELOPER_ID = "4c4ca53f-c059-4ffa-966e-9d29dd405daf" X_CLIENT = f"{DEVELOPER_ID} - {APPLICATION_NAME} {__version__}" diff --git a/homeassistant/components/habitica/icons.json b/homeassistant/components/habitica/icons.json index f4f045523d4f2a1cf03a7000213297e3655a7196..85adfa09304d33325f9948f28e6c6ae57b887e1f 100644 --- a/homeassistant/components/habitica/icons.json +++ b/homeassistant/components/habitica/icons.json @@ -253,6 +253,12 @@ "duedate_options": "mdi:calendar-blank", "reminder_options": "mdi:reminder" } + }, + "create_todo": { + "service": "mdi:pencil-box-outline", + "sections": { + "developer_options": "mdi:test-tube" + } } } } diff --git a/homeassistant/components/habitica/services.py b/homeassistant/components/habitica/services.py index f1e92d863ca085a220341028782bed8677cd85de..bb8f69a8d115cb3b96321ece3c8394b03ac6fdce 100644 --- a/homeassistant/components/habitica/services.py +++ b/homeassistant/components/habitica/services.py @@ -79,6 +79,7 @@ from .const import ( SERVICE_CAST_SKILL, SERVICE_CREATE_HABIT, SERVICE_CREATE_REWARD, + SERVICE_CREATE_TODO, SERVICE_GET_TASKS, SERVICE_LEAVE_QUEST, SERVICE_REJECT_QUEST, @@ -214,6 +215,7 @@ SERVICE_TASK_TYPE_MAP = { SERVICE_UPDATE_HABIT: TaskType.HABIT, SERVICE_CREATE_HABIT: TaskType.HABIT, SERVICE_UPDATE_TODO: TaskType.TODO, + SERVICE_CREATE_TODO: TaskType.TODO, } @@ -811,20 +813,14 @@ def async_setup_services(hass: HomeAssistant) -> None: # noqa: C901 schema=SERVICE_UPDATE_TASK_SCHEMA, supports_response=SupportsResponse.ONLY, ) - hass.services.async_register( - DOMAIN, - SERVICE_CREATE_REWARD, - create_or_update_task, - schema=SERVICE_CREATE_TASK_SCHEMA, - supports_response=SupportsResponse.ONLY, - ) - hass.services.async_register( - DOMAIN, - SERVICE_CREATE_HABIT, - create_or_update_task, - schema=SERVICE_CREATE_TASK_SCHEMA, - supports_response=SupportsResponse.ONLY, - ) + for service in (SERVICE_CREATE_HABIT, SERVICE_CREATE_REWARD, SERVICE_CREATE_TODO): + hass.services.async_register( + DOMAIN, + service, + create_or_update_task, + schema=SERVICE_CREATE_TASK_SCHEMA, + supports_response=SupportsResponse.ONLY, + ) hass.services.async_register( DOMAIN, SERVICE_API_CALL, diff --git a/homeassistant/components/habitica/services.yaml b/homeassistant/components/habitica/services.yaml index 2464b39529b14e3be27bc207953aae04d5d3c7cb..acbe4e62824cbc7598f86a7a9211a10fd37f4539 100644 --- a/homeassistant/components/habitica/services.yaml +++ b/homeassistant/components/habitica/services.yaml @@ -271,7 +271,7 @@ update_todo: checklist_options: collapsed: true fields: - add_checklist_item: + add_checklist_item: &add_checklist_item required: false selector: text: @@ -295,7 +295,7 @@ update_todo: duedate_options: collapsed: true fields: - date: + date: &due_date required: false selector: date: @@ -308,7 +308,7 @@ update_todo: reminder_options: collapsed: true fields: - reminder: + reminder: &reminder required: false selector: text: @@ -328,3 +328,14 @@ update_todo: label: "🗑ï¸" tag_options: *tag_options developer_options: *developer_options +create_todo: + fields: + config_entry: *config_entry + name: *name + notes: *notes + add_checklist_item: *add_checklist_item + priority: *priority + date: *due_date + reminder: *reminder + tag: *tag + developer_options: *developer_options diff --git a/homeassistant/components/habitica/strings.json b/homeassistant/components/habitica/strings.json index d77bbd6f2be476de273037c2c73c73b894d9ae94..513c0b36b27e7632d1ff9c1558218470cedf3b10 100644 --- a/homeassistant/components/habitica/strings.json +++ b/homeassistant/components/habitica/strings.json @@ -49,7 +49,9 @@ "clear_reminder_name": "Clear all reminders", "clear_reminder_description": "Remove all reminders from a Habitica task.", "reminder_options_name": "Reminders", - "reminder_options_description": "Add, remove or clear reminders of a Habitica task." + "reminder_options_description": "Add, remove or clear reminders of a Habitica task.", + "date_name": "Due date", + "date_description": "The to-do's due date." }, "config": { "abort": { @@ -929,8 +931,8 @@ "description": "[%key:component::habitica::common::priority_description%]" }, "date": { - "name": "Due date", - "description": "The to-do's due date." + "name": "[%key:component::habitica::common::date_name%]", + "description": "[%key:component::habitica::common::date_description%]" }, "clear_date": { "name": "Clear due date", @@ -971,7 +973,7 @@ "description": "[%key:component::habitica::common::checklist_options_description%]" }, "duedate_options": { - "name": "Due date", + "name": "[%key:component::habitica::common::date_name%]", "description": "Set, update or remove due dates of a to-do." }, "reminder_options": { @@ -987,6 +989,54 @@ "description": "[%key:component::habitica::common::developer_options_description%]" } } + }, + "create_todo": { + "name": "Create to-do", + "description": "Adds a new to-do.", + "fields": { + "config_entry": { + "name": "[%key:component::habitica::common::config_entry_name%]", + "description": "Select the Habitica account to create a to-do." + }, + "name": { + "name": "[%key:component::habitica::common::task_name%]", + "description": "[%key:component::habitica::common::name_description%]" + }, + "notes": { + "name": "[%key:component::habitica::common::notes_name%]", + "description": "[%key:component::habitica::common::notes_description%]" + }, + "tag": { + "name": "[%key:component::habitica::common::tag_name%]", + "description": "[%key:component::habitica::common::tag_description%]" + }, + "alias": { + "name": "[%key:component::habitica::common::alias_name%]", + "description": "[%key:component::habitica::common::alias_description%]" + }, + "priority": { + "name": "[%key:component::habitica::common::priority_name%]", + "description": "[%key:component::habitica::common::priority_description%]" + }, + "date": { + "name": "[%key:component::habitica::common::date_name%]", + "description": "[%key:component::habitica::common::date_description%]" + }, + "reminder": { + "name": "[%key:component::habitica::common::reminder_name%]", + "description": "[%key:component::habitica::common::reminder_description%]" + }, + "add_checklist_item": { + "name": "[%key:component::habitica::common::add_checklist_item_name%]", + "description": "[%key:component::habitica::common::add_checklist_item_description%]" + } + }, + "sections": { + "developer_options": { + "name": "[%key:component::habitica::common::developer_options_name%]", + "description": "[%key:component::habitica::common::developer_options_description%]" + } + } } }, "selector": { diff --git a/tests/components/habitica/test_services.py b/tests/components/habitica/test_services.py index 3fd477f6858f9a20fee02d472330e325f0f3d935..238cb8412ba5b12abce0d31e236fa0781cb48188 100644 --- a/tests/components/habitica/test_services.py +++ b/tests/components/habitica/test_services.py @@ -55,6 +55,7 @@ from homeassistant.components.habitica.const import ( SERVICE_CAST_SKILL, SERVICE_CREATE_HABIT, SERVICE_CREATE_REWARD, + SERVICE_CREATE_TODO, SERVICE_GET_TASKS, SERVICE_LEAVE_QUEST, SERVICE_REJECT_QUEST, @@ -1002,7 +1003,7 @@ async def test_update_task_exceptions( ) @pytest.mark.parametrize( "service", - [SERVICE_CREATE_REWARD, SERVICE_CREATE_HABIT], + [SERVICE_CREATE_REWARD, SERVICE_CREATE_HABIT, SERVICE_CREATE_TODO], ) @pytest.mark.usefixtures("habitica") async def test_create_task_exceptions( @@ -1509,6 +1510,102 @@ async def test_update_todo( habitica.update_task.assert_awaited_with(UUID(task_id), call_args) +@pytest.mark.parametrize( + ("service_data", "call_args"), + [ + ( + { + ATTR_NAME: "TITLE", + }, + Task(type=TaskType.TODO, text="TITLE"), + ), + ( + { + ATTR_NAME: "TITLE", + ATTR_NOTES: "NOTES", + }, + Task(type=TaskType.TODO, text="TITLE", notes="NOTES"), + ), + ( + { + ATTR_NAME: "TITLE", + ATTR_ADD_CHECKLIST_ITEM: "Checklist-item", + }, + Task( + type=TaskType.TODO, + text="TITLE", + checklist=[ + Checklist( + id=UUID("12345678-1234-5678-1234-567812345678"), + text="Checklist-item", + completed=False, + ), + ], + ), + ), + ( + { + ATTR_NAME: "TITLE", + ATTR_PRIORITY: "trivial", + }, + Task(type=TaskType.TODO, text="TITLE", priority=TaskPriority.TRIVIAL), + ), + ( + { + ATTR_NAME: "TITLE", + ATTR_DATE: "2025-03-05", + }, + Task(type=TaskType.TODO, text="TITLE", date=datetime(2025, 3, 5)), + ), + ( + { + ATTR_NAME: "TITLE", + ATTR_REMINDER: ["2025-02-25T00:00"], + }, + Task( + type=TaskType.TODO, + text="TITLE", + reminders=[ + Reminders( + id=UUID("12345678-1234-5678-1234-567812345678"), + time=datetime(2025, 2, 25, 0, 0), + startDate=None, + ) + ], + ), + ), + ( + { + ATTR_NAME: "TITLE", + ATTR_ALIAS: "ALIAS", + }, + Task(type=TaskType.TODO, text="TITLE", alias="ALIAS"), + ), + ], +) +@pytest.mark.usefixtures("mock_uuid4") +async def test_create_todo( + hass: HomeAssistant, + config_entry: MockConfigEntry, + habitica: AsyncMock, + service_data: dict[str, Any], + call_args: Task, +) -> None: + """Test Habitica create todo action.""" + + await hass.services.async_call( + DOMAIN, + SERVICE_CREATE_TODO, + service_data={ + ATTR_CONFIG_ENTRY: config_entry.entry_id, + **service_data, + }, + return_response=True, + blocking=True, + ) + habitica.create_task.assert_awaited_with(call_args) + + async def test_tags( hass: HomeAssistant, config_entry: MockConfigEntry,