parent
a14cc326fc
commit
c294477aee
@ -118,6 +118,20 @@ def _href(collection, href):
|
|||||||
href.lstrip("/"))
|
href.lstrip("/"))
|
||||||
|
|
||||||
|
|
||||||
|
def _date_to_datetime(date_):
|
||||||
|
"""Transform a date to a UTC datetime.
|
||||||
|
|
||||||
|
If date_ is a datetime without timezone, return as UTC datetime. If date_
|
||||||
|
is already a datetime with timezone, return as is.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not isinstance(date_, datetime):
|
||||||
|
date_ = datetime.combine(date_, datetime.min.time())
|
||||||
|
if not date_.tzinfo:
|
||||||
|
date_ = date_.replace(tzinfo=timezone.utc)
|
||||||
|
return date_
|
||||||
|
|
||||||
|
|
||||||
def _comp_match(item, filter_, scope="collection"):
|
def _comp_match(item, filter_, scope="collection"):
|
||||||
"""Check whether the ``item`` matches the comp ``filter_``.
|
"""Check whether the ``item`` matches the comp ``filter_``.
|
||||||
|
|
||||||
@ -220,100 +234,128 @@ def _time_range_match(vobject_item, filter_, child_name):
|
|||||||
if child_name == "VEVENT":
|
if child_name == "VEVENT":
|
||||||
# TODO: check if there's a timezone
|
# TODO: check if there's a timezone
|
||||||
dtstart = child.dtstart.value
|
dtstart = child.dtstart.value
|
||||||
if isinstance(dtstart, datetime) and not dtstart.tzinfo:
|
|
||||||
dtstart = dtstart.replace(tzinfo=timezone.utc)
|
|
||||||
|
|
||||||
if not isinstance(dtstart, datetime):
|
if child.rruleset:
|
||||||
dtstart_is_datetime = False
|
dtstarts = child.getrruleset(addRDate=True)
|
||||||
# TODO: changing dates to datetimes may be wrong because of tz
|
|
||||||
dtstart = datetime.combine(dtstart, datetime.min.time()).replace(
|
|
||||||
tzinfo=timezone.utc)
|
|
||||||
else:
|
else:
|
||||||
dtstart_is_datetime = True
|
dtstarts = (dtstart,)
|
||||||
|
|
||||||
dtend = getattr(child, "dtend", None)
|
dtend = getattr(child, "dtend", None)
|
||||||
|
if dtend is not None:
|
||||||
|
dtend = dtend.value
|
||||||
|
original_duration = (dtend - dtstart).total_seconds()
|
||||||
|
dtend = _date_to_datetime(dtend)
|
||||||
|
|
||||||
duration = getattr(child, "duration", None)
|
duration = getattr(child, "duration", None)
|
||||||
|
if duration is not None:
|
||||||
|
original_duration = duration = duration.value
|
||||||
|
|
||||||
|
for dtstart in dtstarts:
|
||||||
|
dtstart_is_datetime = isinstance(dtstart, datetime)
|
||||||
|
dtstart = _date_to_datetime(dtstart)
|
||||||
|
|
||||||
|
if dtstart > end:
|
||||||
|
break
|
||||||
|
|
||||||
if dtend is not None:
|
if dtend is not None:
|
||||||
# Line 1
|
# Line 1
|
||||||
dtend = dtend.value
|
dtend = dtstart + timedelta(seconds=original_duration)
|
||||||
if not isinstance(dtend, datetime):
|
if start < dtend and end > dtstart:
|
||||||
dtend = datetime.combine(dtend, datetime.min.time()).replace(
|
return True
|
||||||
tzinfo=timezone.utc)
|
|
||||||
if isinstance(dtend, datetime) and not dtend.tzinfo:
|
|
||||||
dtend = dtend.replace(tzinfo=timezone.utc)
|
|
||||||
|
|
||||||
return start < dtend and end > dtstart
|
|
||||||
elif duration is not None:
|
elif duration is not None:
|
||||||
duration = duration.value
|
if original_duration is None:
|
||||||
|
original_duration = duration.seconds
|
||||||
if duration.seconds > 0:
|
if duration.seconds > 0:
|
||||||
# Line 2
|
# Line 2
|
||||||
return start < dtstart + duration and end > dtstart
|
if start < dtstart + duration and end > dtstart:
|
||||||
else:
|
return True
|
||||||
|
elif start <= dtstart and end > dtstart:
|
||||||
# Line 3
|
# Line 3
|
||||||
return start <= dtstart and end > dtstart
|
return True
|
||||||
elif dtstart_is_datetime:
|
elif dtstart_is_datetime:
|
||||||
# Line 4
|
# Line 4
|
||||||
return start <= dtstart and end > dtstart
|
if start <= dtstart and end > dtstart:
|
||||||
else:
|
return True
|
||||||
|
elif start < dtstart + timedelta(days=1) and end > dtstart:
|
||||||
# Line 5
|
# Line 5
|
||||||
return start < dtstart + timedelta(days=1) and end > dtstart
|
return True
|
||||||
|
|
||||||
elif child_name == "VTODO":
|
elif child_name == "VTODO":
|
||||||
# TODO: implement this
|
|
||||||
dtstart = getattr(child, "dtstart", None)
|
dtstart = getattr(child, "dtstart", None)
|
||||||
duration = getattr(child, "duration", None)
|
duration = getattr(child, "duration", None)
|
||||||
due = getattr(child, "due", None)
|
due = getattr(child, "due", None)
|
||||||
completed = getattr(child, "completed", None)
|
completed = getattr(child, "completed", None)
|
||||||
created = getattr(child, "created", None)
|
created = getattr(child, "created", None)
|
||||||
|
|
||||||
|
if dtstart is not None:
|
||||||
|
dtstart = _date_to_datetime(dtstart.value)
|
||||||
|
if duration is not None:
|
||||||
|
duration = duration.value
|
||||||
|
if due is not None:
|
||||||
|
due = _date_to_datetime(due.value)
|
||||||
|
if dtstart is not None:
|
||||||
|
original_duration = (due - dtstart).total_seconds()
|
||||||
|
if completed is not None:
|
||||||
|
completed = _date_to_datetime(completed.value)
|
||||||
|
if created is not None:
|
||||||
|
created = _date_to_datetime(created.value)
|
||||||
|
original_duration = (completed - created).total_seconds()
|
||||||
|
elif created is not None:
|
||||||
|
created = _date_to_datetime(created.value)
|
||||||
|
|
||||||
|
if child.rruleset:
|
||||||
|
reference_dates = child.getrruleset(addRDate=True)
|
||||||
|
else:
|
||||||
|
if dtstart is not None:
|
||||||
|
reference_dates = (dtstart,)
|
||||||
|
elif due is not None:
|
||||||
|
reference_dates = (due,)
|
||||||
|
elif completed is not None:
|
||||||
|
reference_dates = (completed,)
|
||||||
|
elif created is not None:
|
||||||
|
reference_dates = (created,)
|
||||||
|
else:
|
||||||
|
# Line 8
|
||||||
|
return True
|
||||||
|
|
||||||
|
for reference_date in reference_dates:
|
||||||
|
reference_date = _date_to_datetime(reference_date)
|
||||||
|
if reference_date > end:
|
||||||
|
break
|
||||||
|
|
||||||
if dtstart is not None and duration is not None:
|
if dtstart is not None and duration is not None:
|
||||||
# Line 1
|
# Line 1
|
||||||
dtstart = dtstart.value
|
if start <= reference_date + duration and (
|
||||||
if not isinstance(dtstart, datetime):
|
end > reference_date or
|
||||||
dtstart = (datetime.combine(dtstart, datetime.min.time())
|
end >= reference_date + duration):
|
||||||
.replace(tzinfo=timezone.utc))
|
return True
|
||||||
duration = duration.value
|
|
||||||
return (start <= dtstart + duration and
|
|
||||||
(end > dtstart or end >= dtstart + duration))
|
|
||||||
elif dtstart is not None and due is not None:
|
elif dtstart is not None and due is not None:
|
||||||
# Line 2
|
# Line 2
|
||||||
dtstart = dtstart.value
|
due = reference_date + timedelta(seconds=original_duration)
|
||||||
if not isinstance(dtstart, datetime):
|
if (start < due or start <= reference_date) and (
|
||||||
dtstart = (datetime.combine(dtstart, datetime.min.time())
|
end > reference_date or end >= due):
|
||||||
.replace(tzinfo=timezone.utc))
|
return True
|
||||||
due = due.value
|
|
||||||
if not isinstance(due, datetime):
|
|
||||||
due = datetime.combine(due, datetime.min.time()).replace(
|
|
||||||
tzinfo=timezone.utc)
|
|
||||||
return ((start < due or start <= dtstart) and
|
|
||||||
(end > dtstart or end >= due))
|
|
||||||
elif dtstart is not None:
|
elif dtstart is not None:
|
||||||
# Line 3
|
if start <= reference_date and end > reference_date:
|
||||||
dtstart = dtstart.value
|
return True
|
||||||
if not isinstance(dtstart, datetime):
|
|
||||||
dtstart = (datetime.combine(dtstart, datetime.min.time())
|
|
||||||
.replace(tzinfo=timezone.utc))
|
|
||||||
return start <= dtstart and end > dtstart
|
|
||||||
elif due is not None:
|
elif due is not None:
|
||||||
# Line 4
|
# Line 4
|
||||||
due = due.value
|
if start < reference_date and end >= reference_date:
|
||||||
if not isinstance(due, datetime):
|
return True
|
||||||
due = datetime.combine(due, datetime.min.time()).replace(
|
|
||||||
tzinfo=timezone.utc)
|
|
||||||
return start < due and end >= due
|
|
||||||
elif completed is not None and created is not None:
|
elif completed is not None and created is not None:
|
||||||
# Line 5
|
# Line 5
|
||||||
completed = completed.value
|
completed = reference_date + timedelta(
|
||||||
created = created.value
|
seconds=original_duration)
|
||||||
return ((start <= created or start <= completed) and
|
if (start <= reference_date or start <= completed) and (
|
||||||
(end >= created or end >= completed))
|
end >= reference_date or end >= completed):
|
||||||
|
return True
|
||||||
elif completed is not None:
|
elif completed is not None:
|
||||||
# Line 6
|
# Line 6
|
||||||
completed = completed.value
|
if start <= reference_date and end >= reference_date:
|
||||||
return start <= completed and end >= completed
|
return True
|
||||||
elif created is not None:
|
elif created is not None:
|
||||||
# Line 7
|
# Line 7
|
||||||
created = created.value
|
if end > reference_date:
|
||||||
return end > created
|
|
||||||
else:
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
elif child_name == "VJOURNAL":
|
elif child_name == "VJOURNAL":
|
||||||
@ -321,25 +363,27 @@ def _time_range_match(vobject_item, filter_, child_name):
|
|||||||
|
|
||||||
if dtstart is not None:
|
if dtstart is not None:
|
||||||
dtstart = dtstart.value
|
dtstart = dtstart.value
|
||||||
if not isinstance(dtstart, datetime):
|
if child.rruleset:
|
||||||
dtstart_is_datetime = False
|
dtstarts = child.getrruleset(addRDate=True)
|
||||||
# TODO: changing dates to datetimes may be wrong because of tz
|
|
||||||
dtstart = (datetime.combine(dtstart, datetime.min.time())
|
|
||||||
.replace(tzinfo=timezone.utc))
|
|
||||||
else:
|
else:
|
||||||
dtstart_is_datetime = True
|
dtstarts = (dtstart,)
|
||||||
|
|
||||||
|
for dtstart in dtstarts:
|
||||||
|
dtstart_is_datetime = isinstance(dtstart, datetime)
|
||||||
|
dtstart = _date_to_datetime(dtstart)
|
||||||
|
|
||||||
|
if dtstart > end:
|
||||||
|
break
|
||||||
|
|
||||||
if dtstart_is_datetime:
|
if dtstart_is_datetime:
|
||||||
# Line 1
|
# Line 1
|
||||||
return start <= dtstart and end > dtstart
|
if start <= dtstart and end > dtstart:
|
||||||
else:
|
|
||||||
# Line 2
|
|
||||||
return start < dtstart + timedelta(days=1) and end > dtstart
|
|
||||||
else:
|
|
||||||
# Line 3
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
elif start < dtstart + timedelta(days=1) and end > dtstart:
|
||||||
|
# Line 2
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _text_match(vobject_item, filter_, child_name, attrib_name=None):
|
def _text_match(vobject_item, filter_, child_name, attrib_name=None):
|
||||||
|
@ -27,5 +27,6 @@ UID:event2
|
|||||||
SUMMARY:Event2
|
SUMMARY:Event2
|
||||||
DTSTART;TZID=Europe/Paris:20130902T180000
|
DTSTART;TZID=Europe/Paris:20130902T180000
|
||||||
DTEND;TZID=Europe/Paris:20130902T190000
|
DTEND;TZID=Europe/Paris:20130902T190000
|
||||||
|
RRULE:FREQ=WEEKLY
|
||||||
END:VEVENT
|
END:VEVENT
|
||||||
END:VCALENDAR
|
END:VCALENDAR
|
||||||
|
@ -25,7 +25,8 @@ UID:journal2
|
|||||||
DTSTAMP:19950817T000000
|
DTSTAMP:19950817T000000
|
||||||
DTSTART;TZID=Europe/Paris:20000101T100000
|
DTSTART;TZID=Europe/Paris:20000101T100000
|
||||||
SUMMARY:happy new year
|
SUMMARY:happy new year
|
||||||
DESCRIPTION: Happy new year 2001 !
|
DESCRIPTION: Happy new year !
|
||||||
|
RRULE:FREQ=YEARLY
|
||||||
END:VJOURNAL
|
END:VJOURNAL
|
||||||
|
|
||||||
END:VCALENDAR
|
END:VCALENDAR
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
BEGIN:VCALENDAR
|
|
||||||
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
|
|
||||||
VERSION:2.0
|
|
||||||
BEGIN:VTODO
|
|
||||||
CREATED:20130903T091105Z
|
|
||||||
LAST-MODIFIED:20130903T091108Z
|
|
||||||
DTSTAMP:20130903T091108Z
|
|
||||||
UID:todo
|
|
||||||
SUMMARY:Todo
|
|
||||||
END:VTODO
|
|
||||||
END:VCALENDAR
|
|
@ -22,5 +22,7 @@ END:VTIMEZONE
|
|||||||
BEGIN:VTODO
|
BEGIN:VTODO
|
||||||
DTSTART;TZID=Europe/Paris:20130901T220000
|
DTSTART;TZID=Europe/Paris:20130901T220000
|
||||||
DURATION:PT1H
|
DURATION:PT1H
|
||||||
|
SUMMARY:Todo
|
||||||
|
UID:todo
|
||||||
END:VTODO
|
END:VTODO
|
||||||
END:VCALENDAR
|
END:VCALENDAR
|
||||||
|
@ -22,5 +22,6 @@ END:VTIMEZONE
|
|||||||
BEGIN:VTODO
|
BEGIN:VTODO
|
||||||
DTSTART;TZID=Europe/Paris:20130901T180000
|
DTSTART;TZID=Europe/Paris:20130901T180000
|
||||||
DUE;TZID=Europe/Paris:20130903T180000
|
DUE;TZID=Europe/Paris:20130903T180000
|
||||||
|
RRULE:FREQ=MONTHLY
|
||||||
END:VTODO
|
END:VTODO
|
||||||
END:VCALENDAR
|
END:VCALENDAR
|
||||||
|
@ -69,8 +69,8 @@ class BaseRequests:
|
|||||||
"""Add a todo."""
|
"""Add a todo."""
|
||||||
self.request(
|
self.request(
|
||||||
"PUT", "/calendar.ics/", "BEGIN:VCALENDAR\r\nEND:VCALENDAR")
|
"PUT", "/calendar.ics/", "BEGIN:VCALENDAR\r\nEND:VCALENDAR")
|
||||||
todo = get_file_content("todo.ics")
|
todo = get_file_content("todo1.ics")
|
||||||
path = "/calendar.ics/todo.ics"
|
path = "/calendar.ics/todo1.ics"
|
||||||
status, headers, answer = self.request("PUT", path, todo)
|
status, headers, answer = self.request("PUT", path, todo)
|
||||||
assert status == 201
|
assert status == 201
|
||||||
status, headers, answer = self.request("GET", path)
|
status, headers, answer = self.request("GET", path)
|
||||||
@ -341,7 +341,7 @@ class BaseRequests:
|
|||||||
answer = self._test_filter(["""
|
answer = self._test_filter(["""
|
||||||
<C:comp-filter name="VCALENDAR">
|
<C:comp-filter name="VCALENDAR">
|
||||||
<C:comp-filter name="VEVENT">
|
<C:comp-filter name="VEVENT">
|
||||||
<C:time-range start="20130903T000000Z" end="20131001T000000Z"/>
|
<C:time-range start="20130903T000000Z" end="20130908T000000Z"/>
|
||||||
</C:comp-filter>
|
</C:comp-filter>
|
||||||
</C:comp-filter>"""], items=5)
|
</C:comp-filter>"""], items=5)
|
||||||
assert "href>/calendar.ics/event1.ics</" not in answer
|
assert "href>/calendar.ics/event1.ics</" not in answer
|
||||||
@ -372,6 +372,41 @@ class BaseRequests:
|
|||||||
assert "href>/calendar.ics/event4.ics</" not in answer
|
assert "href>/calendar.ics/event4.ics</" not in answer
|
||||||
assert "href>/calendar.ics/event5.ics</" not in answer
|
assert "href>/calendar.ics/event5.ics</" not in answer
|
||||||
|
|
||||||
|
def test_time_range_filter_events_rrule(self):
|
||||||
|
"""Report request with time-range filter on events with rrules."""
|
||||||
|
answer = self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:time-range start="20130801T000000Z" end="20131001T000000Z"/>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""], "event", items=2)
|
||||||
|
assert "href>/calendar.ics/event1.ics</" in answer
|
||||||
|
assert "href>/calendar.ics/event2.ics</" in answer
|
||||||
|
answer = self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:time-range start="20140801T000000Z" end="20141001T000000Z"/>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""], "event", items=2)
|
||||||
|
assert "href>/calendar.ics/event1.ics</" not in answer
|
||||||
|
assert "href>/calendar.ics/event2.ics</" in answer
|
||||||
|
answer = self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:time-range start="20120801T000000Z" end="20121001T000000Z"/>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""], "event", items=2)
|
||||||
|
assert "href>/calendar.ics/event1.ics</" not in answer
|
||||||
|
assert "href>/calendar.ics/event2.ics</" not in answer
|
||||||
|
answer = self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:time-range start="20130903T000000Z" end="20130907T000000Z"/>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""], "event", items=2)
|
||||||
|
assert "href>/calendar.ics/event1.ics</" not in answer
|
||||||
|
assert "href>/calendar.ics/event2.ics</" not in answer
|
||||||
|
|
||||||
def test_time_range_filter_todos(self):
|
def test_time_range_filter_todos(self):
|
||||||
"""Report request with time-range filter on todos."""
|
"""Report request with time-range filter on todos."""
|
||||||
answer = self._test_filter(["""
|
answer = self._test_filter(["""
|
||||||
@ -431,6 +466,41 @@ class BaseRequests:
|
|||||||
</C:comp-filter>"""], "todo", items=8)
|
</C:comp-filter>"""], "todo", items=8)
|
||||||
assert "href>/calendar.ics/todo7.ics</" in answer
|
assert "href>/calendar.ics/todo7.ics</" in answer
|
||||||
|
|
||||||
|
def test_time_range_filter_todos_rrule(self):
|
||||||
|
"""Report request with time-range filter on todos with rrules."""
|
||||||
|
answer = self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VTODO">
|
||||||
|
<C:time-range start="20130801T000000Z" end="20131001T000000Z"/>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""], "todo", items=2)
|
||||||
|
assert "href>/calendar.ics/todo1.ics</" in answer
|
||||||
|
assert "href>/calendar.ics/todo2.ics</" in answer
|
||||||
|
answer = self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VTODO">
|
||||||
|
<C:time-range start="20140801T000000Z" end="20141001T000000Z"/>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""], "todo", items=2)
|
||||||
|
assert "href>/calendar.ics/todo1.ics</" not in answer
|
||||||
|
assert "href>/calendar.ics/todo2.ics</" in answer
|
||||||
|
answer = self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VTODO">
|
||||||
|
<C:time-range start="20140902T000000Z" end="20140903T000000Z"/>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""], "todo", items=2)
|
||||||
|
assert "href>/calendar.ics/todo1.ics</" not in answer
|
||||||
|
assert "href>/calendar.ics/todo2.ics</" in answer
|
||||||
|
answer = self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VTODO">
|
||||||
|
<C:time-range start="20140904T000000Z" end="20140914T000000Z"/>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""], "todo", items=2)
|
||||||
|
assert "href>/calendar.ics/todo1.ics</" not in answer
|
||||||
|
assert "href>/calendar.ics/todo2.ics</" not in answer
|
||||||
|
|
||||||
def test_time_range_filter_journals(self):
|
def test_time_range_filter_journals(self):
|
||||||
"""Report request with time-range filter on journals."""
|
"""Report request with time-range filter on journals."""
|
||||||
answer = self._test_filter(["""
|
answer = self._test_filter(["""
|
||||||
@ -467,7 +537,7 @@ class BaseRequests:
|
|||||||
</C:comp-filter>
|
</C:comp-filter>
|
||||||
</C:comp-filter>"""], "journal", items=3)
|
</C:comp-filter>"""], "journal", items=3)
|
||||||
assert "href>/calendar.ics/journal1.ics</" not in answer
|
assert "href>/calendar.ics/journal1.ics</" not in answer
|
||||||
assert "href>/calendar.ics/journal2.ics</" not in answer
|
assert "href>/calendar.ics/journal2.ics</" in answer
|
||||||
assert "href>/calendar.ics/journal3.ics</" not in answer
|
assert "href>/calendar.ics/journal3.ics</" not in answer
|
||||||
answer = self._test_filter(["""
|
answer = self._test_filter(["""
|
||||||
<C:comp-filter name="VCALENDAR">
|
<C:comp-filter name="VCALENDAR">
|
||||||
@ -479,6 +549,33 @@ class BaseRequests:
|
|||||||
assert "href>/calendar.ics/journal2.ics</" in answer
|
assert "href>/calendar.ics/journal2.ics</" in answer
|
||||||
assert "href>/calendar.ics/journal3.ics</" in answer
|
assert "href>/calendar.ics/journal3.ics</" in answer
|
||||||
|
|
||||||
|
def test_time_range_filter_journals_rrule(self):
|
||||||
|
"""Report request with time-range filter on journals with rrules."""
|
||||||
|
answer = self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VJOURNAL">
|
||||||
|
<C:time-range start="19991229T000000Z" end="20000202T000000Z"/>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""], "journal", items=2)
|
||||||
|
assert "href>/calendar.ics/journal1.ics</" not in answer
|
||||||
|
assert "href>/calendar.ics/journal2.ics</" in answer
|
||||||
|
answer = self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VJOURNAL">
|
||||||
|
<C:time-range start="20051229T000000Z" end="20060202T000000Z"/>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""], "journal", items=2)
|
||||||
|
assert "href>/calendar.ics/journal1.ics</" not in answer
|
||||||
|
assert "href>/calendar.ics/journal2.ics</" in answer
|
||||||
|
answer = self._test_filter(["""
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VJOURNAL">
|
||||||
|
<C:time-range start="20060102T000000Z" end="20060202T000000Z"/>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>"""], "journal", items=2)
|
||||||
|
assert "href>/calendar.ics/journal1.ics</" not in answer
|
||||||
|
assert "href>/calendar.ics/journal2.ics</" not in answer
|
||||||
|
|
||||||
|
|
||||||
class TestMultiFileSystem(BaseRequests, BaseTest):
|
class TestMultiFileSystem(BaseRequests, BaseTest):
|
||||||
"""Base class for filesystem tests."""
|
"""Base class for filesystem tests."""
|
||||||
|
Loading…
Reference in New Issue
Block a user