diff --git a/src/uds/REST/methods/calendarrules.py b/src/uds/REST/methods/calendarrules.py index 4dfa08e72..47222c50b 100644 --- a/src/uds/REST/methods/calendarrules.py +++ b/src/uds/REST/methods/calendarrules.py @@ -81,8 +81,19 @@ class CalendarRuleItem(types.rest.BaseRestItem): id: str name: str comments: str - start: datetime.datetime - end: datetime.datetime | None + start: datetime.datetime = dataclasses.field( + metadata={ + "description": "ISO 8601 date-time. Without UTC offset it is taken as UTC. " + "Integer timestamps are rejected." + } + ) + end: datetime.datetime | None = dataclasses.field( + metadata={ + "description": "Last day of the rule, ISO 8601 (date or date-time). Only the calendar day " + "is used, as sent, without converting it to UTC. Returned as the last instant of that day. " + "Null means no end." + } + ) frequency: str interval: int duration: int diff --git a/tests/REST/methods/calendars/__init__.py b/tests/REST/methods/calendars/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/REST/methods/calendars/test_rule_api_schema.py b/tests/REST/methods/calendars/test_rule_api_schema.py new file mode 100644 index 000000000..ace6b5588 --- /dev/null +++ b/tests/REST/methods/calendars/test_rule_api_schema.py @@ -0,0 +1,50 @@ +# +# Copyright (c) 2026 Virtual Cable S.L. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Virtual Cable S.L. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" +Author: Andres Schumann, aschumann at virtualcable dot es +""" + +import typing + +from tests.utils.test import UDSTestCase +from uds.core import types +from uds.REST.methods.calendarrules import CalendarRuleItem + + +class CalendarRuleApiSchemaTest(UDSTestCase): + def _description(self, field: str) -> str: + schema = CalendarRuleItem.api_components().schemas["CalendarRuleItem"] + assert isinstance(schema, types.rest.api.Schema) + return typing.cast(str, schema.properties[field].description or "") + + def test_start_documents_iso_8601(self) -> None: + self.assertIn("ISO 8601", self._description("start")) + + def test_end_documents_iso_8601_calendar_day(self) -> None: + description = self._description("end") + self.assertIn("ISO 8601", description) + self.assertIn("calendar day", description)