Subject: Re: bug#64023: 29.0.91; gnus-icalendar does not update timestamp when description is empty

From: Reindert-Jan Ekker <[email-masked]>
Date: Fri, 16 Jun 2023 20:45:48 +0200

As a little exercise I've been writing some unit tests for the bug you
fixed regarding updates to events with empty description. Patch is
attached. Looking forward to any feedback.

>From 67859adc32616c2251f507b89010968cc9246034 Mon Sep 17 00:00:00 2001
From: reindert <[email-masked]>
Date: Fri, 16 Jun 2023 20:39:00 +0200
Subject: [PATCH] ; * test/lisp/gnus/gnus-icalendar-tests.el: Add tests for
 Bug#64023

---
 test/lisp/gnus/gnus-icalendar-tests.el | 167 +++++++++++++++++++++++++
 1 file changed, 167 insertions(+)

diff --git a/test/lisp/gnus/gnus-icalendar-tests.el b/test/lisp/gnus/gnus-icalendar-tests.el
index 8f89e8f..aab9a88 100644
--- a/test/lisp/gnus/gnus-icalendar-tests.el
+++ b/test/lisp/gnus/gnus-icalendar-tests.el
@@ -27,6 +27,7 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 (require 'gnus-icalendar)

@@ -255,5 +256,171 @@ gnus-icalendary-weekly-byday
 <2020-09-21 14:00-14:30 +1w>")))
       (setenv "TZ" tz))))
 
+
+(ert-deftest gnus-icalendar-org-entry-from-ics ()
+  "Test creation of org mode entry from ics string."
+  ;; Use this form so as not to rely on system tz database.
+  ;; Eg hydra.nixos.org.
+  (setenv "TZ" "CET-1CEST,M3.5.0/2,M10.5.0/3")
+  (let ((event (gnus-icalendar-tests--get-ical-event "BEGIN:VCALENDAR
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+VERSION:2.0
+METHOD:REQUEST
+BEGIN:VEVENT
+UID:5e61e65c-c991-4e42-bd41-44fcf057ea11
+SUMMARY:test appointment
+ORGANIZER;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:[email-masked]
+ATTENDEE;CN=Me;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:[email-masked]
+ATTENDEE;CN=Myself;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:[email-masked]
+DTSTART;TZID=Europe/Brussels:20230811T160000
+DTEND;TZID=Europe/Brussels:20230811T170000
+DESCRIPTION;ALTREP=\"data:text/html,%3Cbody%3ELet's%20code%3C%2Fbody%3E\":Let's code
+LOCATION:At home
+END:VEVENT
+END:VCALENDAR")))
+    (should (string= (substring-no-properties (gnus-icalendar-event->org-entry event nil))
+                     "* test appointment (At home)
+:PROPERTIES:
+:ICAL_EVENT: t
+:ID:       5e61e65c-c991-4e42-bd41-44fcf057ea11
+:ORGANIZER: [email-masked]
+:LOCATION: At home
+:PARTICIPATION_TYPE: non-participant
+:REQ_PARTICIPANTS: Me, Myself
+:OPT_PARTICIPANTS:
+:RRULE:
+:REPLY:    Not replied yet
+:END:
+
+  <2023-08-11 16:00-17:00>
+
+  Let's code"))))
+
+
+(ert-deftest gnus-icalendar-org-entry-from-ics-no-loc-no-desc ()
+  "Test creation of org mode entry from ics string, no location, no description."
+  ;; Use this form so as not to rely on system tz database.
+  ;; Eg hydra.nixos.org.
+  (setenv "TZ" "CET-1CEST,M3.5.0/2,M10.5.0/3")
+  (let ((event (gnus-icalendar-tests--get-ical-event "BEGIN:VCALENDAR
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+VERSION:2.0
+METHOD:REQUEST
+BEGIN:VEVENT
+UID:5e61e65c-c991-4e42-bd41-44fcf057ea11
+SUMMARY:test appointment
+ORGANIZER;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:[email-masked]
+ATTENDEE;CN=Me;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:[email-masked]
+ATTENDEE;CN=Myself;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:[email-masked]
+DTSTART;TZID=Europe/Brussels:20230811T160000
+DTEND;TZID=Europe/Brussels:20230811T170000
+END:VEVENT
+END:VCALENDAR")))
+    (should (string= (substring-no-properties (gnus-icalendar-event->org-entry event nil))
+                     "* test appointment
+:PROPERTIES:
+:ICAL_EVENT: t
+:ID:       5e61e65c-c991-4e42-bd41-44fcf057ea11
+:ORGANIZER: [email-masked]
+:LOCATION:
+:PARTICIPATION_TYPE: non-participant
+:REQ_PARTICIPANTS: Me, Myself
+:OPT_PARTICIPANTS:
+:RRULE:
+:REPLY:    Not replied yet
+:END:
+
+  <2023-08-11 16:00-17:00>
+
+  No description"))))
+
+
+(defconst gnus-icalendar-tests--org-entry-no-desc
+  "* Org entry with empty description
+:PROPERTIES:
+:ICAL_EVENT: t
+:ID:       xxx-11-yyy
+:ORGANIZER: No idea
+:LOCATION: Nowhere
+:PARTICIPATION_TYPE: non-participant
+:REQ_PARTICIPANTS:
+:OPT_PARTICIPANTS:
+:RRULE:
+:REPLY:    Not replied yet
+:END:
+
+  <2023-01-01 13:00-14:00>")
+
+
+(defun gnus-icalender-tests--get-updated-event (description)
+  "Create updated event with DESCRIPTION and new date 2024-01-01.
+
+If DESCRIPTION is nil, we don't add a description line at all."
+  ;; Use this form so as not to rely on system tz database.
+  ;; Eg hydra.nixos.org.
+  (setenv "TZ" "CET-1CEST,M3.5.0/2,M10.5.0/3")
+  (let ((description (if description (format "DESCRIPTION:%s\n" description) "")))
+    (gnus-icalendar-tests--get-ical-event (format "BEGIN:VCALENDAR
+METHOD:REQUEST
+BEGIN:VEVENT
+UID:xxx-11-yyy
+SUMMARY:Updated event
+ORGANIZER;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:[email-masked]
+DTSTART;TZID=Europe/Brussels:20240101T180000
+DTEND;TZID=Europe/Brussels:20240101T190000
+%s
+LOCATION:unknown
+END:VEVENT
+END:VCALENDAR" description))))
+
+
+(ert-deftest gnus-icalendar-update-org-event-no-description-add ()
+  "Test for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=64023 .
+
+Update an existing org event that has no description; add description.
+Check timestamp has changed."
+  (ert-with-temp-file
+      calendar-file :suffix ".org" :text gnus-icalendar-tests--org-entry-no-desc
+      (gnus-icalendar--update-org-event (gnus-icalender-tests--get-updated-event "New description")
+                                        'accepted `(,calendar-file))
+      (with-current-buffer (find-buffer-visiting calendar-file)
+        (let ((new-entry (buffer-substring-no-properties (point-min) (point-max))))
+          (should (string-match-p (regexp-quote "<2024-01-01 18:00-19:00>") new-entry))
+          (should (string-match-p (regexp-quote "New description") new-entry))
+          (should-not (string-match-p (regexp-quote "<2023-01-01 13:00-14:00>") new-entry))
+          (should-not (string-match-p (regexp-quote "No description") new-entry))))))
+
+
+(ert-deftest gnus-icalendar-update-org-event-keep-no-description ()
+  "Test for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=64023 .
+
+Update an existing org event that has no description; keep it empty.
+Check timestamp has changed."
+  (ert-with-temp-file
+      calendar-file :suffix ".org" :text gnus-icalendar-tests--org-entry-no-desc
+      (let ((event (gnus-icalender-tests--get-updated-event nil)))
+        (gnus-icalendar--update-org-event event 'accepted `(,calendar-file))
+        (with-current-buffer (find-buffer-visiting calendar-file)
+          (let ((new-entry (buffer-substring-no-properties (point-min) (point-max))))
+            (should (string-match-p (regexp-quote "<2024-01-01 18:00-19:00>") new-entry))
+            (should (string-match-p (regexp-quote "No description") new-entry))
+            (should-not (string-match-p (regexp-quote "<2023-01-01 13:00-14:00>") new-entry)))))))
+
+
+(ert-deftest gnus-icalendar-update-org-event-remove-description ()
+  "Test for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=64023 .
+
+Update an existing org event that has a description; set description empty."
+  (ert-with-temp-file
+      calendar-file :suffix ".org" :text gnus-icalendar-tests--org-entry-no-desc
+      (let ((event (gnus-icalender-tests--get-updated-event nil)))
+        (oset event :description nil)
+        (gnus-icalendar--update-org-event event'accepted `(,calendar-file))
+        (with-current-buffer (find-buffer-visiting calendar-file)
+          (let ((new-entry (buffer-substring-no-properties (point-min) (point-max))))
+            (should (string-match-p (regexp-quote "<2024-01-01 18:00-19:00>") new-entry))
+            (should (string-match-p (regexp-quote "No description") new-entry))
+            (should-not (string-match-p (regexp-quote "<2023-01-01 13:00-14:00>") new-entry)))))))
+
 (provide 'gnus-icalendar-tests)
 ;;; gnus-icalendar-tests.el ends here
-- 
2.40.1

Robert Pluim <[email-masked]> writes:

> (please keep the bug address in CC)
>
>>>>>> On Mon, 12 Jun 2023 20:16:30 +0200, Reindert-Jan Ekker <[email-masked]> said:
>
>     Reindert-Jan> Yes, that works!
>
> OK. Eli, emacs-29 or master? Itʼs a pretty small change, but itʼs not
> a regression as such.
>
>     Reindert-Jan> By the way, what is the intended behaviour of
>     Reindert-Jan> gnus-icalendar--cancel-org-event? It seems to search for a property "DT"
>     Reindert-Jan> that does not exist (at least in my files), so it does not change the
>     Reindert-Jan> event. Is this a bug or am I missing some configuration somewhere?
>
> It looks like a bug. I canʼt find any code creating such a property,
> the current code inserts the timestamp in the body of the org entry.
>
> Robert

-- 
Reindert-Jan Ekker
Code Sensei