mirror of
https://github.com/EDeev/y.calendarkin.git
synced 2026-10-08 00:39:27 +03:00
Тесты разбора календаря (события на сегодня, повторения, UNTIL, проверка ссылки, текст уведомления). Образ по тегу v* публикуется в GHCR и dcr.deev.su.
84 lines
4.2 KiB
Python
84 lines
4.2 KiB
Python
from datetime import datetime, timedelta
|
||
|
||
import pytz
|
||
|
||
import script
|
||
|
||
TZ = pytz.timezone("Europe/Moscow")
|
||
|
||
|
||
def make_ics(events):
|
||
body = "\r\n".join(events)
|
||
return ("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//test//EN\r\n" + body + "\r\nEND:VCALENDAR\r\n").encode()
|
||
|
||
|
||
def vevent(uid, start, end, summary, extra=""):
|
||
return (f"BEGIN:VEVENT\r\nUID:{uid}\r\nDTSTART;TZID=Europe/Moscow:{start:%Y%m%dT%H%M%S}\r\n"
|
||
f"DTEND;TZID=Europe/Moscow:{end:%Y%m%dT%H%M%S}\r\nSUMMARY:{summary}\r\n{extra}END:VEVENT")
|
||
|
||
|
||
def test_parse_ical_url_accepts_only_yandex_export():
|
||
ok = "https://calendar.yandex.ru/export/ics.xml?private_token=abc&tz_id=Asia/Krasnoyarsk"
|
||
assert script.parse_ical_url(ok) == "Asia/Krasnoyarsk"
|
||
assert script.parse_ical_url("https://calendar.yandex.ru/export/ics.xml?private_token=abc") == "Europe/Moscow"
|
||
assert script.parse_ical_url("https://calendar.yandex.ru/x?tz_id=Not/AZone") == "Europe/Moscow"
|
||
for bad in ("http://calendar.yandex.ru/export/ics.xml", "https://127.0.0.1/ics", "file:///etc/passwd",
|
||
"https://calendar.yandex.ru.evil.com/ics", "https://example.com/?tz_id=Europe/Moscow"):
|
||
assert script.parse_ical_url(bad) is None, bad
|
||
|
||
|
||
def test_text_ical_today_events_and_recurrence(tmp_path, monkeypatch):
|
||
monkeypatch.setattr(script, "ICAL_DIR", str(tmp_path))
|
||
now = datetime.now(TZ).replace(tzinfo=None, second=0, microsecond=0)
|
||
today = now.replace(hour=10, minute=0)
|
||
|
||
events = [
|
||
vevent("once", today, today + timedelta(hours=1), "Разовое <важное> & срочное",
|
||
"DESCRIPTION:Описание\r\nORGANIZER:mailto:boss@example.com\r\n"),
|
||
vevent("weekly", today.replace(hour=12) - timedelta(weeks=3),
|
||
today.replace(hour=13) - timedelta(weeks=3), "Еженедельное", "RRULE:FREQ=WEEKLY\r\n"),
|
||
vevent("tomorrow", today + timedelta(days=1), today + timedelta(days=1, hours=1), "Завтра"),
|
||
]
|
||
(tmp_path / "1.ics").write_bytes(make_ics(events))
|
||
|
||
found = {e[3]["name"]: e for e in script.text_ical(1, TZ)}
|
||
assert set(found) == {"Разовое <важное> & срочное", "Еженедельное"}
|
||
assert found["Еженедельное"][1].hour == 12
|
||
|
||
text = script.message_form(1, found["Разовое <важное> & срочное"][3])
|
||
assert "<важное> & срочное" in text
|
||
assert "boss@example.com" in text and "mailto:" not in text
|
||
assert "10:00 — 11:00" in text and str(now.year) not in text
|
||
|
||
|
||
def test_message_form_hides_empty_fields():
|
||
event = {"name": "Встреча", "desc": "", "org": "", "all_day": False,
|
||
"datetime": [datetime(2026, 1, 1, 9, 0), datetime(2026, 1, 1, 9, 30)]}
|
||
text = script.message_form(0, event)
|
||
assert "Описание" not in text and "Организатор" not in text
|
||
assert "09:00 — 09:30" in text
|
||
|
||
|
||
def test_missing_calendar_file_gives_no_events(tmp_path, monkeypatch):
|
||
monkeypatch.setattr(script, "ICAL_DIR", str(tmp_path))
|
||
assert script.text_ical(42, TZ) == []
|
||
|
||
|
||
def test_until_not_in_utc(tmp_path, monkeypatch):
|
||
# повторяющиеся события с UNTIL местным временем или датой раньше роняли разбор календаря
|
||
monkeypatch.setattr(script, "ICAL_DIR", str(tmp_path))
|
||
now = datetime.now(TZ).replace(tzinfo=None, second=0, microsecond=0)
|
||
first = now.replace(hour=9, minute=0) - timedelta(weeks=5)
|
||
events = [
|
||
vevent("ended-local", first, first + timedelta(hours=1), "Закончилось",
|
||
f"RRULE:FREQ=WEEKLY;UNTIL={first + timedelta(weeks=2):%Y%m%dT%H%M%S}\r\n"),
|
||
vevent("ended-date", first, first + timedelta(hours=1), "Закончилось датой",
|
||
f"RRULE:FREQ=WEEKLY;UNTIL={first + timedelta(weeks=2):%Y%m%d}\r\n"),
|
||
vevent("running", first, first + timedelta(hours=1), "Идёт",
|
||
f"RRULE:FREQ=WEEKLY;UNTIL={now + timedelta(weeks=4):%Y%m%dT%H%M%S}\r\n"),
|
||
]
|
||
(tmp_path / "2.ics").write_bytes(make_ics(events))
|
||
|
||
names = {e[3]["name"] for e in script.text_ical(2, TZ)}
|
||
assert names == {"Идёт"}
|
||
assert script.until_utc("20260101", TZ) == "20260101T205959Z"
|