diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-13 10:25:10 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-13 10:25:10 +0200 |
| commit | 091abf04a3e9be7ce36a3bc91441048085f56900 (patch) | |
| tree | e757b465b29c48aba51ff425e33e7e4fbe0f6955 /desktop/island/calendar/test_calctl.py | |
| parent | 9bc2dba1f595ed5ed7121d17b3361a718cc3b1a6 (diff) | |
| download | quickshell-091abf04a3e9be7ce36a3bc91441048085f56900.tar.gz quickshell-091abf04a3e9be7ce36a3bc91441048085f56900.zip | |
feat(calendar): calctl creates, edits and deletes events
Edits change only what the form owns: a custom rule, extra alarms and
properties this tool does not know survive, which the test checks on an
event with BYDAY, two alarms and an X- property. Writes go through a
temporary file and a rename so khal, cal-notif and vdirsyncer never read
half a file, and a vdirsyncer sync is started detached afterwards.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop/island/calendar/test_calctl.py')
| -rw-r--r-- | desktop/island/calendar/test_calctl.py | 80 |
1 files changed, 79 insertions, 1 deletions
diff --git a/desktop/island/calendar/test_calctl.py b/desktop/island/calendar/test_calctl.py index e6acd10..98973ee 100644 --- a/desktop/island/calendar/test_calctl.py +++ b/desktop/island/calendar/test_calctl.py @@ -131,7 +131,85 @@ assert run("list", "2026-10-01", "2026-11-01") assert "no event" in run("get", "nope", ok=False) assert "usage" in run("frobnicate", ok=False) -# --- writes (Task 3) go here --- +def ev(**kw): + e = {"calendar": "home", "title": "Dentist", "allDay": False, + "start": "2026-10-15T14:30", "end": "2026-10-15T15:30", + "repeat": "none", "until": "", "alarm": "1h", "location": "", "notes": ""} + e.update(kw) + return json.dumps(e) + + +def no_temp(): + assert not list(tmp.rglob(".calctl-*")), "temp file left behind" + + +# new, timed: the local zone with its VTIMEZONE, the alarm; read back in +# local time. +uid = run("new", ev())["uid"] +f = tmp / "a" / f"{uid}.ics" +t = f.read_text() +assert "DTSTART;TZID=Europe/Rome:20261015T143000" in t, t +assert "BEGIN:VTIMEZONE" in t and "TRIGGER:-PT1H" in t, t +no_temp() +mine = [e for e in run("list", "2026-10-01", "2026-11-01") if e["uid"] == uid] +assert len(mine) == 1, mine +assert mine[0]["start"] == "2026-10-15T14:30" and mine[0]["end"] == "2026-10-15T15:30" +assert mine[0]["alarm"] == "1h" and mine[0]["repeat"] == "none" and mine[0]["color"] == "green" +assert mine[0]["override"] is False +assert run("get", uid)["title"] == "Dentist" + +# all-day, multi-day: exclusive DTEND on disk, inclusive end in JSON. +trip = run("new", ev(title="Trip", allDay=True, start="2026-10-30", end="2026-11-02", alarm="none"))["uid"] +t = (tmp / "a" / f"{trip}.ics").read_text() +assert "DTSTART;VALUE=DATE:20261030" in t and "DTEND;VALUE=DATE:20261103" in t, t +assert "VALARM" not in t +nov = [e for e in run("list", "2026-11-01", "2026-12-01") if e["uid"] == trip] +assert len(nov) == 1 and nov[0]["start"] == "2026-10-30" and nov[0]["end"] == "2026-11-02", nov +assert not [e for e in run("list", "2026-10-01", "2026-10-30") if e["uid"] == trip] + +# weekly with an until-date, across the DST change. +gym = run("new", ev(title="Gym", repeat="weekly", until="2026-10-29"))["uid"] +occ = [e["start"] for e in run("list", "2026-10-01", "2026-12-01") if e["uid"] == gym] +assert occ == ["2026-10-15T14:30", "2026-10-22T14:30", "2026-10-29T14:30"], occ +assert run("get", gym)["until"] == "2026-10-29" + +# edit keeping custom: the rich rule, both alarms and an unknown property +# survive; SEQUENCE goes up. +run("edit", "weird-1", ev(title="Standup v2", start="2026-10-05T09:30", + end="2026-10-05T10:00", repeat="custom", alarm="custom")) +t = (tmp / "a" / "weird.ics").read_text() +assert "BYDAY=MO,WE" in t and t.count("BEGIN:VALARM") == 2 and "X-FOO:bar" in t, t +assert "SUMMARY:Standup v2" in t and "SEQUENCE:1" in t, t +no_temp() + +# edit to presets: the rule goes, the alarms become one. +run("edit", "weird-1", ev(title="Standup v2", start="2026-10-05T09:30", + end="2026-10-05T10:00", repeat="none", alarm="10m")) +t = (tmp / "a" / "weird.ics").read_text() +assert "RRULE" not in t and t.count("BEGIN:VALARM") == 1 and "TRIGGER:-PT10M" in t, t + +# a calendar change moves the file. +run("edit", uid, ev(calendar="birthdays")) +assert not f.exists() and (tmp / "b" / f.name).exists() +assert run("get", uid)["calendar"] == "birthdays" + +# cal-notif's per-event override is reported. +(tmp / "overrides.toml").write_text(f'"{uid}" = ["10m"]\n') +assert run("get", uid)["override"] is True + +# delete. +assert run("delete", uid) == {} +assert not (tmp / "b" / f.name).exists() +assert "no event" in run("get", uid, ok=False) + +# validation: the error envelope, exit 1, nothing written. +before = sorted(p.name for p in tmp.rglob("*.ics")) +assert "title" in run("new", ev(title=" "), ok=False) +assert "end" in run("new", ev(end="2026-10-15T14:00"), ok=False) +assert "calendar" in run("new", ev(calendar="nope"), ok=False) +assert "json" in run("new", "{not json", ok=False) +assert sorted(p.name for p in tmp.rglob("*.ics")) == before +no_temp() shutil.rmtree(tmp) print("test_calctl: ok") |
