diff --git a/homeassistant/components/habitica/calendar.py b/homeassistant/components/habitica/calendar.py index 46191acf270..e890dfa9123 100644 --- a/homeassistant/components/habitica/calendar.py +++ b/homeassistant/components/habitica/calendar.py @@ -3,13 +3,14 @@ from __future__ import annotations from abc import abstractmethod +from dataclasses import asdict from datetime import date, datetime, timedelta from enum import StrEnum from typing import TYPE_CHECKING from uuid import UUID from dateutil.rrule import rrule -from habiticalib import TaskType +from habiticalib import Frequency, TaskType from homeassistant.components.calendar import ( CalendarEntity, @@ -193,6 +194,10 @@ class HabiticaDailiesCalendarEntity(HabiticaCalendarEntity): # only dailies that that are not 'grey dailies' if not (task.Type is TaskType.DAILY and task.everyX): continue + if task.frequency is Frequency.WEEKLY and not any( + asdict(task.repeat).values() + ): + continue recurrences = build_rrule(task) recurrence_dates = self.get_recurrence_dates( @@ -334,6 +339,11 @@ class HabiticaDailyRemindersCalendarEntity(HabiticaCalendarEntity): if not (task.Type is TaskType.DAILY and task.everyX): continue + if task.frequency is Frequency.WEEKLY and not any( + asdict(task.repeat).values() + ): + continue + recurrences = build_rrule(task) recurrences_start = self.start_of_today diff --git a/homeassistant/components/habitica/util.py b/homeassistant/components/habitica/util.py index 0a7c861eb7e..d265d56021a 100644 --- a/homeassistant/components/habitica/util.py +++ b/homeassistant/components/habitica/util.py @@ -2,7 +2,7 @@ from __future__ import annotations -from dataclasses import fields +from dataclasses import asdict, fields import datetime from math import floor from typing import TYPE_CHECKING @@ -34,6 +34,8 @@ def next_due_date(task: TaskData, today: datetime.datetime) -> datetime.date | N if task.everyX == 0 or not task.nextDue: # grey dailies never become due return None + if task.frequency is Frequency.WEEKLY and not any(asdict(task.repeat).values()): + return None if TYPE_CHECKING: assert task.startDate diff --git a/tests/components/habitica/fixtures/duedate_fixture_9.json b/tests/components/habitica/fixtures/duedate_fixture_9.json new file mode 100644 index 00000000000..f908ad0deae --- /dev/null +++ b/tests/components/habitica/fixtures/duedate_fixture_9.json @@ -0,0 +1,51 @@ +{ + "success": true, + "data": [ + { + "_id": "564b9ac9-c53d-4638-9e7f-1cd96fe19baa", + "frequency": "weekly", + "everyX": 1, + "repeat": { + "m": false, + "t": false, + "w": false, + "th": false, + "f": false, + "s": false, + "su": false + }, + "streak": 1, + "nextDue": ["2024-09-20T22:00:00.000Z", "2024-09-27T22:00:00.000Z"], + "yesterDaily": true, + "history": [], + "completed": false, + "collapseChecklist": false, + "type": "daily", + "text": "Zahnseide benutzen", + "notes": "Klicke um Änderungen zu machen!", + "tags": [], + "value": -2.9663035443712333, + "priority": 1, + "attribute": "str", + "challenge": {}, + "group": { + "completedBy": {}, + "assignedUsers": [] + }, + "byHabitica": false, + "startDate": "2024-09-25T22:00:00.000Z", + "daysOfMonth": [], + "weeksOfMonth": [], + "checklist": [], + "reminders": [], + "createdAt": "2024-07-07T17:51:53.268Z", + "updatedAt": "2024-09-21T22:24:20.154Z", + "userId": "5f359083-ef78-4af0-985a-0b2c6d05797c", + "isDue": false, + "id": "564b9ac9-c53d-4638-9e7f-1cd96fe19baa" + } + ], + "notifications": [], + "userV": 589, + "appVersion": "5.28.6" +} diff --git a/tests/components/habitica/fixtures/tasks.json b/tests/components/habitica/fixtures/tasks.json index 3bb646be512..cf6e3864675 100644 --- a/tests/components/habitica/fixtures/tasks.json +++ b/tests/components/habitica/fixtures/tasks.json @@ -598,6 +598,56 @@ "userId": "5f359083-ef78-4af0-985a-0b2c6d05797c", "isDue": false, "id": "6e53f1f5-a315-4edd-984d-8d762e4a08ef" + }, + { + "repeat": { + "m": false, + "t": false, + "w": false, + "th": false, + "f": false, + "s": false, + "su": false + }, + "challenge": {}, + "group": { + "completedBy": {}, + "assignedUsers": [] + }, + "_id": "7d92278b-9361-4854-83b6-0a66b57dce20", + "frequency": "weekly", + "everyX": 1, + "streak": 1, + "nextDue": [ + "2024-12-14T23:00:00.000Z", + "2025-01-18T23:00:00.000Z", + "2025-02-15T23:00:00.000Z", + "2025-03-15T23:00:00.000Z", + "2025-04-19T23:00:00.000Z", + "2025-05-17T23:00:00.000Z" + ], + "yesterDaily": true, + "history": [], + "completed": false, + "collapseChecklist": false, + "type": "daily", + "text": "Lerne eine neue Programmiersprache", + "notes": "Wähle eine Programmiersprache aus, die du noch nicht kennst, und lerne die Grundlagen.", + "tags": [], + "value": -0.9215181434950852, + "priority": 1, + "attribute": "str", + "byHabitica": false, + "startDate": "2024-09-20T23:00:00.000Z", + "daysOfMonth": [], + "weeksOfMonth": [], + "checklist": [], + "reminders": [], + "createdAt": "2024-10-10T15:57:14.304Z", + "updatedAt": "2024-11-27T23:47:29.986Z", + "userId": "5f359083-ef78-4af0-985a-0b2c6d05797c", + "isDue": false, + "id": "7d92278b-9361-4854-83b6-0a66b57dce20" } ], "notifications": [ diff --git a/tests/components/habitica/snapshots/test_services.ambr b/tests/components/habitica/snapshots/test_services.ambr index 3030b228d38..d0062212775 100644 --- a/tests/components/habitica/snapshots/test_services.ambr +++ b/tests/components/habitica/snapshots/test_services.ambr @@ -1166,6 +1166,84 @@ ]), 'yesterDaily': True, }), + dict({ + 'Type': , + 'alias': None, + 'attribute': , + 'byHabitica': False, + 'challenge': dict({ + 'broken': None, + 'id': None, + 'shortName': None, + 'taskId': None, + 'winner': None, + }), + 'checklist': list([ + ]), + 'collapseChecklist': False, + 'completed': False, + 'counterDown': None, + 'counterUp': None, + 'createdAt': datetime.datetime(2024, 10, 10, 15, 57, 14, 304000, tzinfo=datetime.timezone.utc), + 'date': None, + 'daysOfMonth': list([ + ]), + 'down': None, + 'everyX': 1, + 'frequency': , + 'group': dict({ + 'assignedDate': None, + 'assignedUsers': list([ + ]), + 'assignedUsersDetail': dict({ + }), + 'assigningUsername': None, + 'completedBy': dict({ + 'date': None, + 'userId': None, + }), + 'id': None, + 'managerNotes': None, + 'taskId': None, + }), + 'history': list([ + ]), + 'id': UUID('7d92278b-9361-4854-83b6-0a66b57dce20'), + 'isDue': False, + 'nextDue': list([ + datetime.datetime(2024, 12, 14, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 1, 18, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 2, 15, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 3, 15, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 4, 19, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 5, 17, 23, 0, tzinfo=datetime.timezone.utc), + ]), + 'notes': 'Wähle eine Programmiersprache aus, die du noch nicht kennst, und lerne die Grundlagen.', + 'priority': , + 'reminders': list([ + ]), + 'repeat': dict({ + 'f': False, + 'm': False, + 's': False, + 'su': False, + 't': False, + 'th': False, + 'w': False, + }), + 'startDate': datetime.datetime(2024, 9, 20, 23, 0, tzinfo=datetime.timezone.utc), + 'streak': 1, + 'tags': list([ + ]), + 'text': 'Lerne eine neue Programmiersprache', + 'up': None, + 'updatedAt': datetime.datetime(2024, 11, 27, 23, 47, 29, 986000, tzinfo=datetime.timezone.utc), + 'userId': UUID('5f359083-ef78-4af0-985a-0b2c6d05797c'), + 'value': -0.9215181434950852, + 'weeksOfMonth': list([ + ]), + 'yesterDaily': True, + }), dict({ 'Type': , 'alias': None, @@ -3320,6 +3398,84 @@ ]), 'yesterDaily': True, }), + dict({ + 'Type': , + 'alias': None, + 'attribute': , + 'byHabitica': False, + 'challenge': dict({ + 'broken': None, + 'id': None, + 'shortName': None, + 'taskId': None, + 'winner': None, + }), + 'checklist': list([ + ]), + 'collapseChecklist': False, + 'completed': False, + 'counterDown': None, + 'counterUp': None, + 'createdAt': datetime.datetime(2024, 10, 10, 15, 57, 14, 304000, tzinfo=datetime.timezone.utc), + 'date': None, + 'daysOfMonth': list([ + ]), + 'down': None, + 'everyX': 1, + 'frequency': , + 'group': dict({ + 'assignedDate': None, + 'assignedUsers': list([ + ]), + 'assignedUsersDetail': dict({ + }), + 'assigningUsername': None, + 'completedBy': dict({ + 'date': None, + 'userId': None, + }), + 'id': None, + 'managerNotes': None, + 'taskId': None, + }), + 'history': list([ + ]), + 'id': UUID('7d92278b-9361-4854-83b6-0a66b57dce20'), + 'isDue': False, + 'nextDue': list([ + datetime.datetime(2024, 12, 14, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 1, 18, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 2, 15, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 3, 15, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 4, 19, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 5, 17, 23, 0, tzinfo=datetime.timezone.utc), + ]), + 'notes': 'Wähle eine Programmiersprache aus, die du noch nicht kennst, und lerne die Grundlagen.', + 'priority': , + 'reminders': list([ + ]), + 'repeat': dict({ + 'f': False, + 'm': False, + 's': False, + 'su': False, + 't': False, + 'th': False, + 'w': False, + }), + 'startDate': datetime.datetime(2024, 9, 20, 23, 0, tzinfo=datetime.timezone.utc), + 'streak': 1, + 'tags': list([ + ]), + 'text': 'Lerne eine neue Programmiersprache', + 'up': None, + 'updatedAt': datetime.datetime(2024, 11, 27, 23, 47, 29, 986000, tzinfo=datetime.timezone.utc), + 'userId': UUID('5f359083-ef78-4af0-985a-0b2c6d05797c'), + 'value': -0.9215181434950852, + 'weeksOfMonth': list([ + ]), + 'yesterDaily': True, + }), ]), }) # --- @@ -4373,6 +4529,84 @@ ]), 'yesterDaily': True, }), + dict({ + 'Type': , + 'alias': None, + 'attribute': , + 'byHabitica': False, + 'challenge': dict({ + 'broken': None, + 'id': None, + 'shortName': None, + 'taskId': None, + 'winner': None, + }), + 'checklist': list([ + ]), + 'collapseChecklist': False, + 'completed': False, + 'counterDown': None, + 'counterUp': None, + 'createdAt': datetime.datetime(2024, 10, 10, 15, 57, 14, 304000, tzinfo=datetime.timezone.utc), + 'date': None, + 'daysOfMonth': list([ + ]), + 'down': None, + 'everyX': 1, + 'frequency': , + 'group': dict({ + 'assignedDate': None, + 'assignedUsers': list([ + ]), + 'assignedUsersDetail': dict({ + }), + 'assigningUsername': None, + 'completedBy': dict({ + 'date': None, + 'userId': None, + }), + 'id': None, + 'managerNotes': None, + 'taskId': None, + }), + 'history': list([ + ]), + 'id': UUID('7d92278b-9361-4854-83b6-0a66b57dce20'), + 'isDue': False, + 'nextDue': list([ + datetime.datetime(2024, 12, 14, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 1, 18, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 2, 15, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 3, 15, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 4, 19, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 5, 17, 23, 0, tzinfo=datetime.timezone.utc), + ]), + 'notes': 'Wähle eine Programmiersprache aus, die du noch nicht kennst, und lerne die Grundlagen.', + 'priority': , + 'reminders': list([ + ]), + 'repeat': dict({ + 'f': False, + 'm': False, + 's': False, + 'su': False, + 't': False, + 'th': False, + 'w': False, + }), + 'startDate': datetime.datetime(2024, 9, 20, 23, 0, tzinfo=datetime.timezone.utc), + 'streak': 1, + 'tags': list([ + ]), + 'text': 'Lerne eine neue Programmiersprache', + 'up': None, + 'updatedAt': datetime.datetime(2024, 11, 27, 23, 47, 29, 986000, tzinfo=datetime.timezone.utc), + 'userId': UUID('5f359083-ef78-4af0-985a-0b2c6d05797c'), + 'value': -0.9215181434950852, + 'weeksOfMonth': list([ + ]), + 'yesterDaily': True, + }), ]), }) # --- @@ -4876,6 +5110,84 @@ ]), 'yesterDaily': True, }), + dict({ + 'Type': , + 'alias': None, + 'attribute': , + 'byHabitica': False, + 'challenge': dict({ + 'broken': None, + 'id': None, + 'shortName': None, + 'taskId': None, + 'winner': None, + }), + 'checklist': list([ + ]), + 'collapseChecklist': False, + 'completed': False, + 'counterDown': None, + 'counterUp': None, + 'createdAt': datetime.datetime(2024, 10, 10, 15, 57, 14, 304000, tzinfo=datetime.timezone.utc), + 'date': None, + 'daysOfMonth': list([ + ]), + 'down': None, + 'everyX': 1, + 'frequency': , + 'group': dict({ + 'assignedDate': None, + 'assignedUsers': list([ + ]), + 'assignedUsersDetail': dict({ + }), + 'assigningUsername': None, + 'completedBy': dict({ + 'date': None, + 'userId': None, + }), + 'id': None, + 'managerNotes': None, + 'taskId': None, + }), + 'history': list([ + ]), + 'id': UUID('7d92278b-9361-4854-83b6-0a66b57dce20'), + 'isDue': False, + 'nextDue': list([ + datetime.datetime(2024, 12, 14, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 1, 18, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 2, 15, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 3, 15, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 4, 19, 23, 0, tzinfo=datetime.timezone.utc), + datetime.datetime(2025, 5, 17, 23, 0, tzinfo=datetime.timezone.utc), + ]), + 'notes': 'Wähle eine Programmiersprache aus, die du noch nicht kennst, und lerne die Grundlagen.', + 'priority': , + 'reminders': list([ + ]), + 'repeat': dict({ + 'f': False, + 'm': False, + 's': False, + 'su': False, + 't': False, + 'th': False, + 'w': False, + }), + 'startDate': datetime.datetime(2024, 9, 20, 23, 0, tzinfo=datetime.timezone.utc), + 'streak': 1, + 'tags': list([ + ]), + 'text': 'Lerne eine neue Programmiersprache', + 'up': None, + 'updatedAt': datetime.datetime(2024, 11, 27, 23, 47, 29, 986000, tzinfo=datetime.timezone.utc), + 'userId': UUID('5f359083-ef78-4af0-985a-0b2c6d05797c'), + 'value': -0.9215181434950852, + 'weeksOfMonth': list([ + ]), + 'yesterDaily': True, + }), ]), }) # --- diff --git a/tests/components/habitica/snapshots/test_todo.ambr b/tests/components/habitica/snapshots/test_todo.ambr index 25976270622..9cd6d9a540f 100644 --- a/tests/components/habitica/snapshots/test_todo.ambr +++ b/tests/components/habitica/snapshots/test_todo.ambr @@ -49,6 +49,12 @@ 'summary': 'Arbeite an einem kreativen Projekt', 'uid': '6e53f1f5-a315-4edd-984d-8d762e4a08ef', }), + dict({ + 'description': 'Wähle eine Programmiersprache aus, die du noch nicht kennst, und lerne die Grundlagen.', + 'status': 'needs_action', + 'summary': 'Lerne eine neue Programmiersprache', + 'uid': '7d92278b-9361-4854-83b6-0a66b57dce20', + }), ]), }), }) @@ -144,7 +150,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '3', + 'state': '4', }) # --- # name: test_todos[todo.test_user_to_do_s-entry] diff --git a/tests/components/habitica/test_todo.py b/tests/components/habitica/test_todo.py index ea817013169..6453510a97f 100644 --- a/tests/components/habitica/test_todo.py +++ b/tests/components/habitica/test_todo.py @@ -622,6 +622,7 @@ async def test_move_todo_item_exception( ("duedate_fixture_6.json", "2024-10-21"), ("duedate_fixture_7.json", None), ("duedate_fixture_8.json", None), + ("duedate_fixture_9.json", None), ], ids=[ "default", @@ -632,6 +633,7 @@ async def test_move_todo_item_exception( "monthly starts on fixed day", "grey daily", "empty nextDue", + "grey daily no weekdays", ], ) @pytest.mark.usefixtures("set_tz")