#!/usr/bin/python3 # Tests for cal-notif. Run: /usr/bin/python3 test_cal_notif.py # Copyright (C) 2026 Danilo M. # Licensed under the GNU General Public License version 2 only. import importlib.machinery import importlib.util import os import tempfile import time from datetime import datetime, timedelta from pathlib import Path from zoneinfo import ZoneInfo os.environ["TZ"] = "Europe/Rome" # all-day and floating times are local time.tzset() HERE = Path(__file__).resolve().parent _loader = importlib.machinery.SourceFileLoader("cal_notif", str(HERE / "cal-notif")) _spec = importlib.util.spec_from_loader("cal_notif", _loader) cn = importlib.util.module_from_spec(_spec) _loader.exec_module(cn) ROME = ZoneInfo("Europe/Rome") H, M, D = timedelta(hours=1), timedelta(minutes=1), timedelta(days=1) def ics(*events): body = "".join(f"BEGIN:VEVENT\n{e.strip()}\nEND:VEVENT\n" for e in events) return f"BEGIN:VCALENDAR\nVERSION:2.0\n{body}END:VCALENDAR\n".encode() def at(y, mo, d, h=0, mi=0): return datetime(y, mo, d, h, mi, tzinfo=ROME) def test_durations(): assert cn.parse_duration("1d 2h 15m") == D + 2 * H + 15 * M assert cn.parse_duration("90m") == 90 * M assert cn.parse_duration("0m") == timedelta() for bad in ("", "5", "1x", "m", "2h1d"): try: cn.parse_duration(bad) raise AssertionError(bad) except ValueError: pass assert cn.fmt_duration(D + 2 * H) == "1d 2h" assert cn.fmt_duration(timedelta()) == "0m" assert cn.spoken_it(10 * M) == "dieci minuti" assert cn.spoken_it(H) == "un'ora" assert cn.spoken_it(D + 2 * H) == "un giorno e due ore" assert cn.spoken_it(2 * D + H + 21 * M) == "due giorni, un'ora e ventuno minuti" assert cn.number_it(28) == "ventotto" and cn.number_it(45) == "quarantacinque" def test_overrides_roundtrip(): with tempfile.TemporaryDirectory() as d: p = Path(d) / "overrides.toml" ov = {"a@example.org": ["1h", "10m"], 'q"uote@example.org': []} cn.save_overrides(ov, p) assert cn.load_overrides(p) == ov assert cn.load_overrides(Path(d) / "missing.toml") == {} def test_config(): with tempfile.TemporaryDirectory() as d: p = Path(d) / "config.toml" assert cn.load_config(p)["voice"]["lang"] == "it" # no file: defaults p.write_text('snooze = "15m"\n[voice]\nlang = "en-us"\n' '[defaults]\nbd = { offsets = ["1d"], voice = false }\n') c = cn.load_config(p) assert c["snooze"] == "15m" and c["late"] == "10m" assert c["voice"]["lang"] == "en-us" and c["voice"]["lead_silence"] == 0.3 # merged p.write_text('[defaults]\n"*" = ["soon"]\n') try: cn.load_config(p) raise AssertionError except ValueError: pass if __name__ == "__main__": for name, fn in list(globals().items()): if name.startswith("test_"): fn() print("ok", name)