diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-24 16:18:27 -0400 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-24 16:18:27 -0400 |
| commit | d47f4f90bb1c69697a855a662bb07be1e0ccdc33 (patch) | |
| tree | 777d0b786a530cb4190f8e062e0afda2506308d4 /tests/test-chime-notification-boundaries.el | |
| parent | ab8cc4da57fce5d0a59f4db34fb550919a06ea79 (diff) | |
| download | chime-d47f4f90bb1c69697a855a662bb07be1e0ccdc33.tar.gz chime-d47f4f90bb1c69697a855a662bb07be1e0ccdc33.zip | |
Every test hand-wrote the same scaffolding: call a per-file setup, wrap the body in unwind-protect, call a per-file teardown. That's 419 unwind-protect blocks and 68 near-identical setup/teardown defuns, with no shared fixture because ERT has no native per-test setup.
I added a chime-deftest macro in test-bootstrap that creates the test base directory before the body and deletes it afterward, even on failure. I converted the 10 files whose fixture was exactly that base-dir create/delete and whose every test followed the standard shape, dropping their setup/teardown defuns. Files with custom fixtures (modeline state restore, validation reset) keep explicit setup/teardown, since the macro would silently drop their extra logic. I left the 4 tag-bearing integration files alone.
I also moved the near-universal testutil-general and testutil-time requires into test-bootstrap, so individual files no longer repeat them.
Behavior is unchanged: still 800 tests, full suite green. Converted bodies are copied verbatim, so the change only removes scaffolding, never an assertion.
Diffstat (limited to 'tests/test-chime-notification-boundaries.el')
| -rw-r--r-- | tests/test-chime-notification-boundaries.el | 435 |
1 files changed, 191 insertions, 244 deletions
diff --git a/tests/test-chime-notification-boundaries.el b/tests/test-chime-notification-boundaries.el index 853dd4d..fa288f0 100644 --- a/tests/test-chime-notification-boundaries.el +++ b/tests/test-chime-notification-boundaries.el @@ -27,322 +27,269 @@ (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -;; Load test utilities -(require 'testutil-general (expand-file-name "testutil-general.el")) -(require 'testutil-time (expand-file-name "testutil-time.el")) - -;;; Setup and Teardown - -(defun test-chime-notification-boundaries-setup () - "Setup function run before each test." - (chime-create-test-base-dir)) - -(defun test-chime-notification-boundaries-teardown () - "Teardown function run after each test." - (chime-delete-test-base-dir)) - ;;; Exact Matching Tests -(ert-deftest test-chime-notification-boundary-exact-10-minutes () +(chime-deftest test-chime-notification-boundary-exact-10-minutes () "Test that notification fires exactly at 10-minute interval. Event at 14:10, interval 10 minutes, current time 14:00. Should match: current_time + 10 minutes = 14:10 = event_time" - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - (event-time (test-time-today-at 14 10)) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Test Event") - (intervals . ((10 . medium))))) - (result (chime--notifications event))) - ;; Should match: event is exactly 10 minutes away - (should (= 1 (length result)))))) - (test-chime-notification-boundaries-teardown))) - -(ert-deftest test-chime-notification-boundary-9-minutes-no-match () + (let* ((now (test-time-today-at 14 0)) + (event-time (test-time-today-at 14 10)) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Test Event") + (intervals . ((10 . medium))))) + (result (chime--notifications event))) + ;; Should match: event is exactly 10 minutes away + (should (= 1 (length result))))))) + +(chime-deftest test-chime-notification-boundary-9-minutes-no-match () "Test that notification does NOT fire at 9 minutes (1 minute before interval). Event at 14:10, interval 10 minutes, current time 14:01. Should NOT match: current_time + 10 minutes = 14:11 ≠ 14:10" - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 1)) ; 1 minute past the hour - (event-time (test-time-today-at 14 10)) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Test Event") - (intervals . ((10 . medium))))) - (result (chime--notifications event))) - ;; Should NOT match: event is 9 minutes away, not 10 - (should (= 0 (length result)))))) - (test-chime-notification-boundaries-teardown))) - -(ert-deftest test-chime-notification-boundary-11-minutes-no-match () + (let* ((now (test-time-today-at 14 1)) ; 1 minute past the hour + (event-time (test-time-today-at 14 10)) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Test Event") + (intervals . ((10 . medium))))) + (result (chime--notifications event))) + ;; Should NOT match: event is 9 minutes away, not 10 + (should (= 0 (length result))))))) + +(chime-deftest test-chime-notification-boundary-11-minutes-no-match () "Test that notification does NOT fire at 11 minutes (1 minute after interval). Event at 14:11, interval 10 minutes, current time 14:00. Should NOT match: current_time + 10 minutes = 14:10 ≠ 14:11" - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - (event-time (test-time-today-at 14 11)) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Test Event") - (intervals . ((10 . medium))))) - (result (chime--notifications event))) - ;; Should NOT match: event is 11 minutes away, not 10 - (should (= 0 (length result)))))) - (test-chime-notification-boundaries-teardown))) + (let* ((now (test-time-today-at 14 0)) + (event-time (test-time-today-at 14 11)) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Test Event") + (intervals . ((10 . medium))))) + (result (chime--notifications event))) + ;; Should NOT match: event is 11 minutes away, not 10 + (should (= 0 (length result))))))) ;;; Multi-Day Interval Tests -(ert-deftest test-chime-notification-boundary-4-days-exact () +(chime-deftest test-chime-notification-boundary-4-days-exact () "Test notification for event exactly 4 days away. This tests the user's reported bug: event on Saturday (4 days from Tuesday). With default 10-minute interval, should NOT match. Event at Saturday 10:00am, current time Tuesday 10:00am, interval 10 minutes. Should NOT match: Tuesday 10:00 + 10 min = Tuesday 10:10 ≠ Saturday 10:00" - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* ((now (test-time-now)) - ;; Event 4 days from now at same time - (event-time (time-add now (seconds-to-time (* 4 24 3600)))) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Saturday Event") - (intervals . ((10 . medium))))) ; Default 10 minutes - (result (chime--notifications event))) - ;; Should NOT match: event is 4 days away, interval is 10 minutes - (should (= 0 (length result)))))) - (test-chime-notification-boundaries-teardown))) - -(ert-deftest test-chime-notification-boundary-4-days-with-4-day-interval () + (let* ((now (test-time-now)) + ;; Event 4 days from now at same time + (event-time (time-add now (seconds-to-time (* 4 24 3600)))) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Saturday Event") + (intervals . ((10 . medium))))) ; Default 10 minutes + (result (chime--notifications event))) + ;; Should NOT match: event is 4 days away, interval is 10 minutes + (should (= 0 (length result))))))) + +(chime-deftest test-chime-notification-boundary-4-days-with-4-day-interval () "Test notification for event 4 days away with 4-day interval. Event at Saturday 10:00am, current time Tuesday 10:00am, interval 5760 minutes (4 days). Should match: Tuesday 10:00 + 4 days = Saturday 10:00 = event_time" - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* ((now (test-time-now)) - ;; Event exactly 4 days from now - (event-time (time-add now (seconds-to-time (* 4 24 3600)))) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Saturday Event") - (intervals . ((5760 . medium))))) ; 4 days = 5760 minutes - (result (chime--notifications event))) - ;; Should match: event is exactly 4 days away, interval is 4 days - (should (= 1 (length result)))))) - (test-chime-notification-boundaries-teardown))) - -(ert-deftest test-chime-notification-boundary-1-week-interval () + (let* ((now (test-time-now)) + ;; Event exactly 4 days from now + (event-time (time-add now (seconds-to-time (* 4 24 3600)))) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Saturday Event") + (intervals . ((5760 . medium))))) ; 4 days = 5760 minutes + (result (chime--notifications event))) + ;; Should match: event is exactly 4 days away, interval is 4 days + (should (= 1 (length result))))))) + +(chime-deftest test-chime-notification-boundary-1-week-interval () "Test notification for event exactly 1 week away with 1-week interval. Event 7 days from now, interval 10080 minutes (7 days). Should match: current_time + 7 days = event_time" - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* ((now (test-time-now)) - ;; Event exactly 7 days from now - (event-time (time-add now (seconds-to-time (* 7 24 3600)))) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Next Week Event") - (intervals . ((10080 . medium))))) ; 7 days = 10080 minutes - (result (chime--notifications event))) - ;; Should match: event is exactly 7 days away, interval is 7 days - (should (= 1 (length result)))))) - (test-chime-notification-boundaries-teardown))) + (let* ((now (test-time-now)) + ;; Event exactly 7 days from now + (event-time (time-add now (seconds-to-time (* 7 24 3600)))) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Next Week Event") + (intervals . ((10080 . medium))))) ; 7 days = 10080 minutes + (result (chime--notifications event))) + ;; Should match: event is exactly 7 days away, interval is 7 days + (should (= 1 (length result))))))) ;;; Cross-Month Boundary Tests (Testing for day-of-month matching bug) -(ert-deftest test-chime-notification-boundary-same-day-different-month () +(chime-deftest test-chime-notification-boundary-same-day-different-month () "Test that events on same day-of-month but different months do NOT match. This tests for the bug in chime--time= that only compares day:hour:minute. Event on Nov 18 at 10:00, current time Oct 18 at 10:00 minus 10 minutes. Should NOT match even though day-of-month (18) is the same." - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* (;; Oct 18, 2024 at 9:50am - (now (encode-time 0 50 9 18 10 2024)) - ;; Nov 18, 2024 at 10:00am (31 days + 10 minutes later) - (event-time (encode-time 0 0 10 18 11 2024)) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Next Month Event") - (intervals . ((10 . medium))))) - (result (chime--notifications event))) - ;; Should NOT match: different months, even though day-of-month matches - (should (= 0 (length result)))))) - (test-chime-notification-boundaries-teardown))) - -(ert-deftest test-chime-notification-boundary-same-day-different-year () + (let* (;; Oct 18, 2024 at 9:50am + (now (encode-time 0 50 9 18 10 2024)) + ;; Nov 18, 2024 at 10:00am (31 days + 10 minutes later) + (event-time (encode-time 0 0 10 18 11 2024)) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Next Month Event") + (intervals . ((10 . medium))))) + (result (chime--notifications event))) + ;; Should NOT match: different months, even though day-of-month matches + (should (= 0 (length result))))))) + +(chime-deftest test-chime-notification-boundary-same-day-different-year () "Test that events on same day/month but different years do NOT match. Event on Nov 18, 2025 at 10:00, current time Nov 18, 2024 at 9:50. Should NOT match even though month and day-of-month are the same." - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* (;; Nov 18, 2024 at 9:50am - (now (encode-time 0 50 9 18 11 2024)) - ;; Nov 18, 2025 at 10:00am (1 year + 10 minutes later) - (event-time (encode-time 0 0 10 18 11 2025)) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Next Year Event") - (intervals . ((10 . medium))))) - (result (chime--notifications event))) - ;; Should NOT match: different years - (should (= 0 (length result)))))) - (test-chime-notification-boundaries-teardown))) + (let* (;; Nov 18, 2024 at 9:50am + (now (encode-time 0 50 9 18 11 2024)) + ;; Nov 18, 2025 at 10:00am (1 year + 10 minutes later) + (event-time (encode-time 0 0 10 18 11 2025)) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Next Year Event") + (intervals . ((10 . medium))))) + (result (chime--notifications event))) + ;; Should NOT match: different years + (should (= 0 (length result))))))) ;;; Cross-Day Boundary Tests -(ert-deftest test-chime-notification-boundary-crosses-midnight () +(chime-deftest test-chime-notification-boundary-crosses-midnight () "Test notification that crosses midnight boundary. Event at 00:10 (next day), current time 23:50 (today), interval 20 minutes. Should match: 23:50 + 20 minutes = 00:10 next day" - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* ((now (test-time-today-at 23 50)) - ;; 20 minutes later crosses midnight - (event-time (time-add now (seconds-to-time (* 20 60)))) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Midnight Event") - (intervals . ((20 . medium))))) - (result (chime--notifications event))) - ;; Should match: event is exactly 20 minutes away - (should (= 1 (length result)))))) - (test-chime-notification-boundaries-teardown))) - -(ert-deftest test-chime-notification-boundary-just-before-midnight-no-match () + (let* ((now (test-time-today-at 23 50)) + ;; 20 minutes later crosses midnight + (event-time (time-add now (seconds-to-time (* 20 60)))) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Midnight Event") + (intervals . ((20 . medium))))) + (result (chime--notifications event))) + ;; Should match: event is exactly 20 minutes away + (should (= 1 (length result))))))) + +(chime-deftest test-chime-notification-boundary-just-before-midnight-no-match () "Test that notification doesn't fire just before crossing midnight. Event at 00:10 (next day), current time 23:51 (today), interval 20 minutes. Should NOT match: 23:51 + 20 minutes = 00:11 ≠ 00:10" - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* ((now (test-time-today-at 23 51)) - ;; 19 minutes later - (event-time (time-add now (seconds-to-time (* 19 60)))) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Midnight Event") - (intervals . ((20 . medium))))) - (result (chime--notifications event))) - ;; Should NOT match: event is 19 minutes away, not 20 - (should (= 0 (length result)))))) - (test-chime-notification-boundaries-teardown))) + (let* ((now (test-time-today-at 23 51)) + ;; 19 minutes later + (event-time (time-add now (seconds-to-time (* 19 60)))) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Midnight Event") + (intervals . ((20 . medium))))) + (result (chime--notifications event))) + ;; Should NOT match: event is 19 minutes away, not 20 + (should (= 0 (length result))))))) ;;; Multiple Interval Tests -(ert-deftest test-chime-notification-boundary-multiple-intervals-one-matches () +(chime-deftest test-chime-notification-boundary-multiple-intervals-one-matches () "Test that only matching intervals trigger notifications. Event at 14:10, current time 14:00, intervals 10 and 20 minutes. Should match only the 10-minute interval." - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - (event-time (test-time-today-at 14 10)) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Test Event") - (intervals . ((10 . medium) (20 . high))))) - (result (chime--notifications event))) - ;; Should match only 10-minute interval - (should (= 1 (length result)))))) - (test-chime-notification-boundaries-teardown))) - -(ert-deftest test-chime-notification-boundary-multiple-intervals-all-match () + (let* ((now (test-time-today-at 14 0)) + (event-time (test-time-today-at 14 10)) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Test Event") + (intervals . ((10 . medium) (20 . high))))) + (result (chime--notifications event))) + ;; Should match only 10-minute interval + (should (= 1 (length result))))))) + +(chime-deftest test-chime-notification-boundary-multiple-intervals-all-match () "Test that multiple matching intervals all trigger. Event at 14:20, current time 14:00, intervals 10 and 20 minutes. At 14:00, only 20-minute interval should match. At 14:10, only 10-minute interval should match." - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - (event-time (test-time-today-at 14 20)) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Test Event") - (intervals . ((10 . medium) (20 . high))))) - (result (chime--notifications event))) - ;; At 14:00, event is 20 minutes away, so only 20-minute interval matches - (should (= 1 (length result))))) - - ;; Now test at 14:10 (10 minutes before event) - (let ((now-2 (test-time-today-at 14 10))) - (with-test-time now-2 - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Test Event") - (intervals . ((10 . medium) (20 . high))))) - (result (chime--notifications event))) - ;; At 14:10, event is 10 minutes away, so only 10-minute interval matches - (should (= 1 (length result))))))) - (test-chime-notification-boundaries-teardown))) + (let* ((now (test-time-today-at 14 0)) + (event-time (test-time-today-at 14 20)) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Test Event") + (intervals . ((10 . medium) (20 . high))))) + (result (chime--notifications event))) + ;; At 14:00, event is 20 minutes away, so only 20-minute interval matches + (should (= 1 (length result))))) + + ;; Now test at 14:10 (10 minutes before event) + (let ((now-2 (test-time-today-at 14 10))) + (with-test-time now-2 + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Test Event") + (intervals . ((10 . medium) (20 . high))))) + (result (chime--notifications event))) + ;; At 14:10, event is 10 minutes away, so only 10-minute interval matches + (should (= 1 (length result)))))))) ;;; Escalating Notification Tests -(ert-deftest test-chime-notification-boundary-escalating-intervals () +(chime-deftest test-chime-notification-boundary-escalating-intervals () "Test escalating notifications: 1 day, 1 hour, 10 minutes before event. Simulates the common use case of multiple notifications at different times." - (test-chime-notification-boundaries-setup) - (unwind-protect - (let* ((base-time (test-time-today-at 10 0)) - (event-time (time-add base-time (seconds-to-time (* 24 3600)))) ; 1 day later - (timestamp-str (test-timestamp-string event-time))) - - ;; Test 1: 24 hours before (1 day interval) - (with-test-time base-time - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Important Event") - (intervals . ((1440 . low) (60 . medium) (10 . high))))) - (result (chime--notifications event))) - ;; Should match 1440-minute (1 day) interval - (should (= 1 (length result))))) - - ;; Test 2: 1 hour before (60-minute interval) - (let ((time-1h-before (time-add event-time (seconds-to-time (* -60 60))))) - (with-test-time time-1h-before - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Important Event") - (intervals . ((1440 . low) (60 . medium) (10 . high))))) - (result (chime--notifications event))) - ;; Should match 60-minute interval - (should (= 1 (length result)))))) - - ;; Test 3: 10 minutes before (10-minute interval) - (let ((time-10m-before (time-add event-time (seconds-to-time (* -10 60))))) - (with-test-time time-10m-before - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Important Event") - (intervals . ((1440 . low) (60 . medium) (10 . high))))) - (result (chime--notifications event))) - ;; Should match 10-minute interval - (should (= 1 (length result))))))) - (test-chime-notification-boundaries-teardown))) + (let* ((base-time (test-time-today-at 10 0)) + (event-time (time-add base-time (seconds-to-time (* 24 3600)))) ; 1 day later + (timestamp-str (test-timestamp-string event-time))) + + ;; Test 1: 24 hours before (1 day interval) + (with-test-time base-time + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Important Event") + (intervals . ((1440 . low) (60 . medium) (10 . high))))) + (result (chime--notifications event))) + ;; Should match 1440-minute (1 day) interval + (should (= 1 (length result))))) + + ;; Test 2: 1 hour before (60-minute interval) + (let ((time-1h-before (time-add event-time (seconds-to-time (* -60 60))))) + (with-test-time time-1h-before + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Important Event") + (intervals . ((1440 . low) (60 . medium) (10 . high))))) + (result (chime--notifications event))) + ;; Should match 60-minute interval + (should (= 1 (length result)))))) + + ;; Test 3: 10 minutes before (10-minute interval) + (let ((time-10m-before (time-add event-time (seconds-to-time (* -10 60))))) + (with-test-time time-10m-before + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Important Event") + (intervals . ((1440 . low) (60 . medium) (10 . high))))) + (result (chime--notifications event))) + ;; Should match 10-minute interval + (should (= 1 (length result)))))))) (provide 'test-chime-notification-boundaries) ;;; test-chime-notification-boundaries.el ends here |
