;;; test-calendar-sync--get-recurrence-id.el --- Tests for RECURRENCE-ID extraction -*- lexical-binding: t; -*- ;;; Commentary: ;; Unit tests for calendar-sync--get-recurrence-id function. ;; Tests extraction of RECURRENCE-ID property from VEVENT strings. ;; Following quality-engineer.org guidelines: one function per file. ;;; Code: (require 'ert) (add-to-list 'load-path (expand-file-name "." (file-name-directory load-file-name))) (add-to-list 'load-path (expand-file-name "../modules" (file-name-directory load-file-name))) (require 'testutil-calendar-sync) (require 'calendar-sync) ;;; Normal Cases (ert-deftest test-calendar-sync--get-recurrence-id-normal-simple-returns-value () "Test extracting simple RECURRENCE-ID without TZID." (let ((event "BEGIN:VEVENT DTSTART:20260210T090000 RECURRENCE-ID:20260203T090000 SUMMARY:Rescheduled Meeting END:VEVENT")) (should (string= "20260203T090000" (calendar-sync--get-recurrence-id event))))) (ert-deftest test-calendar-sync--get-recurrence-id-normal-with-z-suffix-returns-value () "Test extracting RECURRENCE-ID with UTC Z suffix." (let ((event "BEGIN:VEVENT DTSTART:20260210T170000Z RECURRENCE-ID:20260203T170000Z SUMMARY:UTC Event END:VEVENT")) (should (string= "20260203T170000Z" (calendar-sync--get-recurrence-id event))))) (ert-deftest test-calendar-sync--get-recurrence-id-normal-with-tzid-returns-value () "Test extracting RECURRENCE-ID with TZID parameter. The TZID parameter should be ignored, only value returned." (let ((event "BEGIN:VEVENT DTSTART;TZID=Europe/Tallinn:20260210T170000 RECURRENCE-ID;TZID=Europe/Tallinn:20260203T170000 SUMMARY:Tallinn Meeting END:VEVENT")) (should (string= "20260203T170000" (calendar-sync--get-recurrence-id event))))) (ert-deftest test-calendar-sync--get-recurrence-id-normal-date-only-returns-value () "Test extracting date-only RECURRENCE-ID for all-day event exceptions." (let ((event "BEGIN:VEVENT DTSTART:20260210 RECURRENCE-ID:20260203 SUMMARY:All Day Exception END:VEVENT")) (should (string= "20260203" (calendar-sync--get-recurrence-id event))))) ;;; Boundary Cases (ert-deftest test-calendar-sync--get-recurrence-id-boundary-no-recurrence-id-returns-nil () "Test that event without RECURRENCE-ID returns nil." (let ((event "BEGIN:VEVENT DTSTART:20260203T090000 SUMMARY:Regular Event END:VEVENT")) (should (null (calendar-sync--get-recurrence-id event))))) (ert-deftest test-calendar-sync--get-recurrence-id-boundary-recurrence-id-multiline-returns-partial () "Test RECURRENCE-ID with continuation line (RFC 5545 folding). Note: Current implementation returns partial value for folded lines. Full continuation line support is a future enhancement." (let ((event "BEGIN:VEVENT DTSTART:20260210T090000 RECURRENCE-ID;TZID=America/Los_Angeles;VALUE=DATE-TIME:2026 0203T090000 SUMMARY:Folded Line END:VEVENT")) ;; Current implementation returns partial value before continuation ;; This is acceptable as folded RECURRENCE-ID lines are rare in practice (let ((result (calendar-sync--get-recurrence-id event))) (should result) ;; At minimum, should capture the year portion (should (string-match-p "2026" result))))) (ert-deftest test-calendar-sync--get-recurrence-id-boundary-multiple-params-returns-value () "Test RECURRENCE-ID with multiple parameters." (let ((event "BEGIN:VEVENT DTSTART:20260210T090000 RECURRENCE-ID;TZID=America/Chicago;VALUE=DATE-TIME:20260203T090000 SUMMARY:Multi-param END:VEVENT")) (should (string= "20260203T090000" (calendar-sync--get-recurrence-id event))))) ;;; Error Cases (ert-deftest test-calendar-sync--get-recurrence-id-error-empty-string-returns-nil () "Test that empty event string returns nil." (should (null (calendar-sync--get-recurrence-id "")))) (ert-deftest test-calendar-sync--get-recurrence-id-error-nil-input-returns-nil () "Test that nil input returns nil." (should (null (calendar-sync--get-recurrence-id nil)))) (ert-deftest test-calendar-sync--get-recurrence-id-error-malformed-returns-nil () "Test that malformed event without proper structure returns nil." (should (null (calendar-sync--get-recurrence-id "not a vevent")))) (provide 'test-calendar-sync--get-recurrence-id) ;;; test-calendar-sync--get-recurrence-id.el ends here