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 | |
| 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')
53 files changed, 1705 insertions, 2413 deletions
diff --git a/tests/test-bootstrap.el b/tests/test-bootstrap.el index f53b9f1..40c333a 100644 --- a/tests/test-bootstrap.el +++ b/tests/test-bootstrap.el @@ -45,5 +45,28 @@ ;; Load chime from parent directory (load (expand-file-name "../chime.el") nil t) +;; Load the near-universal test helpers so individual test files don't each +;; repeat the require. testutil-general carries the base-dir fixture used by +;; `chime-deftest' below; testutil-time carries the dynamic-time helpers. +(require 'testutil-general (expand-file-name "testutil-general.el")) +(require 'testutil-time (expand-file-name "testutil-time.el")) + +(defmacro chime-deftest (name arglist &rest body) + "Define an ERT test NAME with chime's standard base-dir fixture. +ARGLIST is the `ert-deftest' argument list (normally nil). When the +first form in BODY is a string it is kept as the test docstring. The +remaining forms run inside the test base directory, created beforehand +with `chime-create-test-base-dir' and removed afterward with +`chime-delete-test-base-dir' even if a form signals." + (declare (indent 2) (doc-string 3)) + (let* ((doc (and (stringp (car body)) (cdr body) (car body))) + (forms (if doc (cdr body) body))) + `(ert-deftest ,name ,arglist + ,@(and doc (list doc)) + (chime-create-test-base-dir) + (unwind-protect + (progn ,@forms) + (chime-delete-test-base-dir))))) + (provide 'test-bootstrap) ;;; test-bootstrap.el ends here diff --git a/tests/test-chime--deduplicate-events-by-title.el b/tests/test-chime--deduplicate-events-by-title.el index 66ec37a..13066eb 100644 --- a/tests/test-chime--deduplicate-events-by-title.el +++ b/tests/test-chime--deduplicate-events-by-title.el @@ -30,10 +30,6 @@ (setq chime-debug t) (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")) - ;;; Test Helpers (defun test-make-event (title) diff --git a/tests/test-chime-12hour-format.el b/tests/test-chime-12hour-format.el index 0fcb91a..c18cbc5 100644 --- a/tests/test-chime-12hour-format.el +++ b/tests/test-chime-12hour-format.el @@ -31,10 +31,6 @@ (setq chime-debug t) (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")) - ;;; Tests for chime--convert-12hour-to-24hour (ert-deftest test-12hour-convert-1pm-to-13 () diff --git a/tests/test-chime-all-day-events.el b/tests/test-chime-all-day-events.el index 1cacf69..168f545 100644 --- a/tests/test-chime-all-day-events.el +++ b/tests/test-chime-all-day-events.el @@ -9,8 +9,6 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-general (expand-file-name "testutil-general.el")) -(require 'testutil-time (expand-file-name "testutil-time.el")) ;;; Helper Functions diff --git a/tests/test-chime-apply-blacklist.el b/tests/test-chime-apply-blacklist.el index abfc3e8..3f16a3d 100644 --- a/tests/test-chime-apply-blacklist.el +++ b/tests/test-chime-apply-blacklist.el @@ -27,9 +27,6 @@ (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -;; Load test utilities -(require 'testutil-general (expand-file-name "testutil-general.el")) - ;;; Setup and Teardown (defun test-chime-apply-blacklist-setup () diff --git a/tests/test-chime-apply-whitelist.el b/tests/test-chime-apply-whitelist.el index 1552ee2..6e3be24 100644 --- a/tests/test-chime-apply-whitelist.el +++ b/tests/test-chime-apply-whitelist.el @@ -27,9 +27,6 @@ (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -;; Load test utilities -(require 'testutil-general (expand-file-name "testutil-general.el")) - ;;; Setup and Teardown (defun test-chime-apply-whitelist-setup () diff --git a/tests/test-chime-async-helpers.el b/tests/test-chime-async-helpers.el index 3e0e562..c7eb5ba 100644 --- a/tests/test-chime-async-helpers.el +++ b/tests/test-chime-async-helpers.el @@ -27,7 +27,6 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-time (expand-file-name "testutil-time.el")) ;;; Setup and Teardown diff --git a/tests/test-chime-check-event.el b/tests/test-chime-check-event.el index e362504..db63c9e 100644 --- a/tests/test-chime-check-event.el +++ b/tests/test-chime-check-event.el @@ -27,8 +27,6 @@ (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")) (require 'testutil-events (expand-file-name "testutil-events.el")) ;;; Normal Cases diff --git a/tests/test-chime-check-interval.el b/tests/test-chime-check-interval.el index 74cbe14..4a79197 100644 --- a/tests/test-chime-check-interval.el +++ b/tests/test-chime-check-interval.el @@ -26,9 +26,6 @@ (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -;; Load test utilities -(require 'testutil-general (expand-file-name "testutil-general.el")) - ;;; Setup and Teardown (defun test-chime-check-interval-setup () diff --git a/tests/test-chime-day-wide-notifications.el b/tests/test-chime-day-wide-notifications.el index 260abfc..b5638fb 100644 --- a/tests/test-chime-day-wide-notifications.el +++ b/tests/test-chime-day-wide-notifications.el @@ -23,7 +23,6 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-time (expand-file-name "testutil-time.el")) (ert-deftest test-chime-day-wide-notifications-normal-wraps-with-medium-severity () "Normal: each generated text is wrapped as (TEXT . \\='medium)." diff --git a/tests/test-chime-day-wide-time-matching.el b/tests/test-chime-day-wide-time-matching.el index 88242e2..1a87326 100644 --- a/tests/test-chime-day-wide-time-matching.el +++ b/tests/test-chime-day-wide-time-matching.el @@ -33,10 +33,6 @@ (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")) - (defmacro test-chime-with-restored-day-wide-alert-times (&rest body) "Run BODY and restore default `chime-day-wide-alert-times' afterwards." (declare (indent 0) (debug t)) diff --git a/tests/test-chime-debug-functions.el b/tests/test-chime-debug-functions.el index 7ef85e5..01e6663 100644 --- a/tests/test-chime-debug-functions.el +++ b/tests/test-chime-debug-functions.el @@ -30,10 +30,6 @@ (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) (require 'chime-debug (expand-file-name "../chime-debug.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-debug-functions-setup () diff --git a/tests/test-chime-edge-coverage.el b/tests/test-chime-edge-coverage.el index 1325e77..0133099 100644 --- a/tests/test-chime-edge-coverage.el +++ b/tests/test-chime-edge-coverage.el @@ -26,7 +26,6 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-time (expand-file-name "testutil-time.el")) (require 'cl-lib) ;;;; chime--day-wide-notification-text fallback (chime.el ~ "t branch") diff --git a/tests/test-chime-event-contract.el b/tests/test-chime-event-contract.el index 697dccb..deeb626 100644 --- a/tests/test-chime-event-contract.el +++ b/tests/test-chime-event-contract.el @@ -25,8 +25,6 @@ (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-general (expand-file-name "testutil-general.el")) -(require 'testutil-time (expand-file-name "testutil-time.el")) (require 'testutil-events (expand-file-name "testutil-events.el")) (ert-deftest test-chime-event-contract-make-event-creates-valid-event () diff --git a/tests/test-chime-event-is-today.el b/tests/test-chime-event-is-today.el index 305749a..deb4f70 100644 --- a/tests/test-chime-event-is-today.el +++ b/tests/test-chime-event-is-today.el @@ -31,10 +31,6 @@ (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")) - ;;; Helpers — build events at real dates (defun test--real-today-at (hour minute) diff --git a/tests/test-chime-extract-time.el b/tests/test-chime-extract-time.el index 120c45b..d2be145 100644 --- a/tests/test-chime-extract-time.el +++ b/tests/test-chime-extract-time.el @@ -28,31 +28,15 @@ (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-extract-time-setup () - "Setup function run before each test." - (chime-create-test-base-dir)) - -(defun test-chime-extract-time-teardown () - "Teardown function run after each test." - (chime-delete-test-base-dir)) - ;;; Tests for org-gcal events -(ert-deftest test-chime-extract-time-gcal-event-from-drawer () +(chime-deftest test-chime-extract-time-gcal-event-from-drawer () "Test that org-gcal events extract timestamps ONLY from :org-gcal: drawer. REFACTORED: Uses dynamic timestamps" - (test-chime-extract-time-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 0)) - (timestamp-str (format-time-string "<%Y-%m-%d %a %H:%M-15:00>" time)) - (test-content (format "* Meeting + (let* ((time (test-time-tomorrow-at 14 0)) + (timestamp-str (format-time-string "<%Y-%m-%d %a %H:%M-15:00>" time)) + (test-content (format "* Meeting :PROPERTIES: :entry-id: abc123@google.com :END: @@ -60,33 +44,30 @@ REFACTORED: Uses dynamic timestamps" %s :END: " timestamp-str)) - (test-file (chime-create-temp-test-file-with-content test-content)) - (test-buffer (find-file-noselect test-file))) - (with-current-buffer test-buffer - (org-mode) - (goto-char (point-min)) - (let* ((marker (point-marker)) - (times (chime--extract-time marker))) - ;; Should extract the timestamp from :org-gcal: drawer - (should (= 1 (length times))) - (should (string-match-p "14:00" (car (car times)))))) - (kill-buffer test-buffer)) - (test-chime-extract-time-teardown))) - -(ert-deftest test-chime-extract-time-gcal-event-ignores-body-timestamps () + (test-file (chime-create-temp-test-file-with-content test-content)) + (test-buffer (find-file-noselect test-file))) + (with-current-buffer test-buffer + (org-mode) + (goto-char (point-min)) + (let* ((marker (point-marker)) + (times (chime--extract-time marker))) + ;; Should extract the timestamp from :org-gcal: drawer + (should (= 1 (length times))) + (should (string-match-p "14:00" (car (car times)))))) + (kill-buffer test-buffer))) + +(chime-deftest test-chime-extract-time-gcal-event-ignores-body-timestamps () "Test that org-gcal events ignore plain timestamps in body text. When an event is rescheduled, old timestamps might remain in the body. The :org-gcal: drawer has the correct time, so we should ignore body text. REFACTORED: Uses dynamic timestamps" - (test-chime-extract-time-setup) - (unwind-protect - (let* ((new-time (test-time-tomorrow-at 14 0)) - (old-time (test-time-today-at 14 0)) - (new-timestamp (test-timestamp-string new-time)) - (old-timestamp (test-timestamp-string old-time)) - (test-content (format "* Meeting + (let* ((new-time (test-time-tomorrow-at 14 0)) + (old-time (test-time-today-at 14 0)) + (new-timestamp (test-timestamp-string new-time)) + (old-timestamp (test-timestamp-string old-time)) + (test-content (format "* Meeting :PROPERTIES: :entry-id: abc123@google.com :END: @@ -95,34 +76,31 @@ REFACTORED: Uses dynamic timestamps" :END: Old time was %s " new-timestamp old-timestamp)) - (test-file (chime-create-temp-test-file-with-content test-content)) - (test-buffer (find-file-noselect test-file))) - (with-current-buffer test-buffer - (org-mode) - (goto-char (point-min)) - (let* ((marker (point-marker)) - (times (chime--extract-time marker))) - ;; Should extract ONLY from drawer (tomorrow), ignore body (today) - (should (= 1 (length times))) - (should (string-match-p "14:00" (car (car times)))) - ;; Verify it's the new timestamp, not the old one - (should (string-match-p (format-time-string "%Y-%m-%d" new-time) (car (car times)))))) - (kill-buffer test-buffer)) - (test-chime-extract-time-teardown))) - -(ert-deftest test-chime-extract-time-gcal-event-ignores-scheduled () + (test-file (chime-create-temp-test-file-with-content test-content)) + (test-buffer (find-file-noselect test-file))) + (with-current-buffer test-buffer + (org-mode) + (goto-char (point-min)) + (let* ((marker (point-marker)) + (times (chime--extract-time marker))) + ;; Should extract ONLY from drawer (tomorrow), ignore body (today) + (should (= 1 (length times))) + (should (string-match-p "14:00" (car (car times)))) + ;; Verify it's the new timestamp, not the old one + (should (string-match-p (format-time-string "%Y-%m-%d" new-time) (car (car times)))))) + (kill-buffer test-buffer))) + +(chime-deftest test-chime-extract-time-gcal-event-ignores-scheduled () "Test that org-gcal events ignore SCHEDULED/DEADLINE properties. For org-gcal events, the :org-gcal: drawer is the source of truth. REFACTORED: Uses dynamic timestamps" - (test-chime-extract-time-setup) - (unwind-protect - (let* ((drawer-time (test-time-tomorrow-at 14 0)) - (scheduled-time (test-time-days-from-now 2)) - (drawer-timestamp (test-timestamp-string drawer-time)) - (scheduled-timestamp (test-timestamp-string scheduled-time)) - (test-content (format "* Meeting + (let* ((drawer-time (test-time-tomorrow-at 14 0)) + (scheduled-time (test-time-days-from-now 2)) + (drawer-timestamp (test-timestamp-string drawer-time)) + (scheduled-timestamp (test-timestamp-string scheduled-time)) + (test-content (format "* Meeting SCHEDULED: %s :PROPERTIES: :entry-id: abc123@google.com @@ -131,33 +109,30 @@ SCHEDULED: %s %s :END: " scheduled-timestamp drawer-timestamp)) - (test-file (chime-create-temp-test-file-with-content test-content)) - (test-buffer (find-file-noselect test-file))) - (with-current-buffer test-buffer - (org-mode) - (goto-char (point-min)) - (let* ((marker (point-marker)) - (times (chime--extract-time marker))) - ;; Should extract ONLY from drawer (tomorrow), ignore SCHEDULED (day after) - (should (= 1 (length times))) - (should (string-match-p "14:00" (car (car times)))) - (should (string-match-p (format-time-string "%Y-%m-%d" drawer-time) (car (car times)))))) - (kill-buffer test-buffer)) - (test-chime-extract-time-teardown))) - -(ert-deftest test-chime-extract-time-gcal-event-multiple-in-drawer () + (test-file (chime-create-temp-test-file-with-content test-content)) + (test-buffer (find-file-noselect test-file))) + (with-current-buffer test-buffer + (org-mode) + (goto-char (point-min)) + (let* ((marker (point-marker)) + (times (chime--extract-time marker))) + ;; Should extract ONLY from drawer (tomorrow), ignore SCHEDULED (day after) + (should (= 1 (length times))) + (should (string-match-p "14:00" (car (car times)))) + (should (string-match-p (format-time-string "%Y-%m-%d" drawer-time) (car (car times)))))) + (kill-buffer test-buffer))) + +(chime-deftest test-chime-extract-time-gcal-event-multiple-in-drawer () "Test that org-gcal events extract all timestamps from :org-gcal: drawer. Some recurring events might have multiple timestamps in the drawer. REFACTORED: Uses dynamic timestamps" - (test-chime-extract-time-setup) - (unwind-protect - (let* ((time1 (test-time-tomorrow-at 14 0)) - (time2 (test-time-days-from-now 2 14 0)) - (timestamp1 (test-timestamp-string time1)) - (timestamp2 (test-timestamp-string time2)) - (test-content (format "* Meeting + (let* ((time1 (test-time-tomorrow-at 14 0)) + (time2 (test-time-days-from-now 2 14 0)) + (timestamp1 (test-timestamp-string time1)) + (timestamp2 (test-timestamp-string time2)) + (test-content (format "* Meeting :PROPERTIES: :entry-id: abc123@google.com :END: @@ -166,153 +141,137 @@ REFACTORED: Uses dynamic timestamps" %s :END: " timestamp1 timestamp2)) - (test-file (chime-create-temp-test-file-with-content test-content)) - (test-buffer (find-file-noselect test-file))) - (with-current-buffer test-buffer - (org-mode) - (goto-char (point-min)) - (let* ((marker (point-marker)) - (times (chime--extract-time marker))) - ;; Should extract both timestamps from drawer - (should (= 2 (length times))) - (should (string-match-p "14:00" (car (car times)))) - (should (string-match-p "14:00" (car (cadr times)))))) - (kill-buffer test-buffer)) - (test-chime-extract-time-teardown))) + (test-file (chime-create-temp-test-file-with-content test-content)) + (test-buffer (find-file-noselect test-file))) + (with-current-buffer test-buffer + (org-mode) + (goto-char (point-min)) + (let* ((marker (point-marker)) + (times (chime--extract-time marker))) + ;; Should extract both timestamps from drawer + (should (= 2 (length times))) + (should (string-match-p "14:00" (car (car times)))) + (should (string-match-p "14:00" (car (cadr times)))))) + (kill-buffer test-buffer))) ;;; Tests for regular org events -(ert-deftest test-chime-extract-time-regular-event-scheduled () +(chime-deftest test-chime-extract-time-regular-event-scheduled () "Test that regular events extract SCHEDULED timestamp. REFACTORED: Uses dynamic timestamps" - (test-chime-extract-time-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 0)) - (timestamp (test-timestamp-string time)) - (test-content (format "* Task + (let* ((time (test-time-tomorrow-at 14 0)) + (timestamp (test-timestamp-string time)) + (test-content (format "* Task SCHEDULED: %s " timestamp)) - (test-file (chime-create-temp-test-file-with-content test-content)) - (test-buffer (find-file-noselect test-file))) - (with-current-buffer test-buffer - (org-mode) - (goto-char (point-min)) - (let* ((marker (point-marker)) - (times (chime--extract-time marker))) - ;; Should extract SCHEDULED timestamp - (should (= 1 (length times))) - (should (string-match-p "14:00" (car (car times)))))) - (kill-buffer test-buffer)) - (test-chime-extract-time-teardown))) - -(ert-deftest test-chime-extract-time-regular-event-deadline () + (test-file (chime-create-temp-test-file-with-content test-content)) + (test-buffer (find-file-noselect test-file))) + (with-current-buffer test-buffer + (org-mode) + (goto-char (point-min)) + (let* ((marker (point-marker)) + (times (chime--extract-time marker))) + ;; Should extract SCHEDULED timestamp + (should (= 1 (length times))) + (should (string-match-p "14:00" (car (car times)))))) + (kill-buffer test-buffer))) + +(chime-deftest test-chime-extract-time-regular-event-deadline () "Test that regular events extract DEADLINE timestamp. REFACTORED: Uses dynamic timestamps" - (test-chime-extract-time-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 17 0)) - (timestamp (test-timestamp-string time)) - (test-content (format "* Task + (let* ((time (test-time-tomorrow-at 17 0)) + (timestamp (test-timestamp-string time)) + (test-content (format "* Task DEADLINE: %s " timestamp)) - (test-file (chime-create-temp-test-file-with-content test-content)) - (test-buffer (find-file-noselect test-file))) - (with-current-buffer test-buffer - (org-mode) - (goto-char (point-min)) - (let* ((marker (point-marker)) - (times (chime--extract-time marker))) - ;; Should extract DEADLINE timestamp - (should (= 1 (length times))) - (should (string-match-p "17:00" (car (car times)))))) - (kill-buffer test-buffer)) - (test-chime-extract-time-teardown))) - -(ert-deftest test-chime-extract-time-regular-event-plain-timestamps () + (test-file (chime-create-temp-test-file-with-content test-content)) + (test-buffer (find-file-noselect test-file))) + (with-current-buffer test-buffer + (org-mode) + (goto-char (point-min)) + (let* ((marker (point-marker)) + (times (chime--extract-time marker))) + ;; Should extract DEADLINE timestamp + (should (= 1 (length times))) + (should (string-match-p "17:00" (car (car times)))))) + (kill-buffer test-buffer))) + +(chime-deftest test-chime-extract-time-regular-event-plain-timestamps () "Test that regular events extract plain timestamps when no SCHEDULED/DEADLINE. REFACTORED: Uses dynamic timestamps" - (test-chime-extract-time-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 0)) - (timestamp (test-timestamp-string time)) - (test-content (format "* Meeting notes + (let* ((time (test-time-tomorrow-at 14 0)) + (timestamp (test-timestamp-string time)) + (test-content (format "* Meeting notes Discussed: %s " timestamp)) - (test-file (chime-create-temp-test-file-with-content test-content)) - (test-buffer (find-file-noselect test-file))) - (with-current-buffer test-buffer - (org-mode) - (goto-char (point-min)) - (let* ((marker (point-marker)) - (times (chime--extract-time marker))) - ;; Should extract plain timestamp - (should (= 1 (length times))) - (should (string-match-p "14:00" (car (car times)))))) - (kill-buffer test-buffer)) - (test-chime-extract-time-teardown))) - -(ert-deftest test-chime-extract-time-regular-event-scheduled-and-plain () + (test-file (chime-create-temp-test-file-with-content test-content)) + (test-buffer (find-file-noselect test-file))) + (with-current-buffer test-buffer + (org-mode) + (goto-char (point-min)) + (let* ((marker (point-marker)) + (times (chime--extract-time marker))) + ;; Should extract plain timestamp + (should (= 1 (length times))) + (should (string-match-p "14:00" (car (car times)))))) + (kill-buffer test-buffer))) + +(chime-deftest test-chime-extract-time-regular-event-scheduled-and-plain () "Test that regular events extract both SCHEDULED and plain timestamps. SCHEDULED/DEADLINE appear first, then plain timestamps. REFACTORED: Uses dynamic timestamps" - (test-chime-extract-time-setup) - (unwind-protect - (let* ((scheduled-time (test-time-tomorrow-at 14 0)) - (plain-time (test-time-days-from-now 2 15 0)) - (scheduled-timestamp (test-timestamp-string scheduled-time)) - (plain-timestamp (format-time-string "<%Y-%m-%d %a %H:%M>" plain-time)) - (test-content (format "* Task + (let* ((scheduled-time (test-time-tomorrow-at 14 0)) + (plain-time (test-time-days-from-now 2 15 0)) + (scheduled-timestamp (test-timestamp-string scheduled-time)) + (plain-timestamp (format-time-string "<%Y-%m-%d %a %H:%M>" plain-time)) + (test-content (format "* Task SCHEDULED: %s Note: also happens %s " scheduled-timestamp plain-timestamp)) - (test-file (chime-create-temp-test-file-with-content test-content)) - (test-buffer (find-file-noselect test-file))) - (with-current-buffer test-buffer - (org-mode) - (goto-char (point-min)) - (let* ((marker (point-marker)) - (times (chime--extract-time marker))) - ;; Should extract both: SCHEDULED first, then plain - (should (= 2 (length times))) - ;; First should be SCHEDULED - (should (string-match-p "14:00" (car (car times)))) - ;; Second should be plain at 15:00 - (should (string-match-p "15:00" (car (cadr times)))))) - (kill-buffer test-buffer)) - (test-chime-extract-time-teardown))) - -(ert-deftest test-chime-extract-time-regular-event-multiple-plain () + (test-file (chime-create-temp-test-file-with-content test-content)) + (test-buffer (find-file-noselect test-file))) + (with-current-buffer test-buffer + (org-mode) + (goto-char (point-min)) + (let* ((marker (point-marker)) + (times (chime--extract-time marker))) + ;; Should extract both: SCHEDULED first, then plain + (should (= 2 (length times))) + ;; First should be SCHEDULED + (should (string-match-p "14:00" (car (car times)))) + ;; Second should be plain at 15:00 + (should (string-match-p "15:00" (car (cadr times)))))) + (kill-buffer test-buffer))) + +(chime-deftest test-chime-extract-time-regular-event-multiple-plain () "Test that regular events extract all plain timestamps. REFACTORED: Uses dynamic timestamps" - (test-chime-extract-time-setup) - (unwind-protect - (let* ((time1 (test-time-tomorrow-at 14 0)) - (time2 (test-time-days-from-now 2 15 0)) - (timestamp1 (test-timestamp-string time1)) - (timestamp2 (test-timestamp-string time2)) - (test-content (format "* Meeting notes + (let* ((time1 (test-time-tomorrow-at 14 0)) + (time2 (test-time-days-from-now 2 15 0)) + (timestamp1 (test-timestamp-string time1)) + (timestamp2 (test-timestamp-string time2)) + (test-content (format "* Meeting notes First discussion: %s Second discussion: %s " timestamp1 timestamp2)) - (test-file (chime-create-temp-test-file-with-content test-content)) - (test-buffer (find-file-noselect test-file))) - (with-current-buffer test-buffer - (org-mode) - (goto-char (point-min)) - (let* ((marker (point-marker)) - (times (chime--extract-time marker))) - ;; Should extract both plain timestamps - (should (= 2 (length times))) - (should (string-match-p "14:00" (car (car times)))) - (should (string-match-p "15:00" (car (cadr times)))))) - (kill-buffer test-buffer)) - (test-chime-extract-time-teardown))) + (test-file (chime-create-temp-test-file-with-content test-content)) + (test-buffer (find-file-noselect test-file))) + (with-current-buffer test-buffer + (org-mode) + (goto-char (point-min)) + (let* ((marker (point-marker)) + (times (chime--extract-time marker))) + ;; Should extract both plain timestamps + (should (= 2 (length times))) + (should (string-match-p "14:00" (car (car times)))) + (should (string-match-p "15:00" (car (cadr times)))))) + (kill-buffer test-buffer))) (provide 'test-chime-extract-time) ;;; test-chime-extract-time.el ends here diff --git a/tests/test-chime-extract-title.el b/tests/test-chime-extract-title.el index d778c7e..f7efd33 100644 --- a/tests/test-chime-extract-title.el +++ b/tests/test-chime-extract-title.el @@ -27,9 +27,6 @@ (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -;; Load test utilities -(require 'testutil-general (expand-file-name "testutil-general.el")) - ;;; Normal Cases (ert-deftest test-chime-extract-title-plain-heading () diff --git a/tests/test-chime-filter-day-wide-events.el b/tests/test-chime-filter-day-wide-events.el index 6e24f00..415598d 100644 --- a/tests/test-chime-filter-day-wide-events.el +++ b/tests/test-chime-filter-day-wide-events.el @@ -28,10 +28,6 @@ (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")) - ;;; Normal Cases (ert-deftest test-chime-filter-day-wide-events-keeps-timed-event () diff --git a/tests/test-chime-format-event-for-tooltip.el b/tests/test-chime-format-event-for-tooltip.el index 5e2cabb..0569477 100644 --- a/tests/test-chime-format-event-for-tooltip.el +++ b/tests/test-chime-format-event-for-tooltip.el @@ -26,222 +26,175 @@ (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-format-event-for-tooltip-setup () - "Setup function run before each test." - (chime-create-test-base-dir)) - -(defun test-chime-format-event-for-tooltip-teardown () - "Teardown function run after each test." - (chime-delete-test-base-dir)) - ;;; Normal Cases -(ert-deftest test-chime-format-event-for-tooltip-normal-minutes () +(chime-deftest test-chime-format-event-for-tooltip-normal-minutes () "Test formatting event with minutes until event. REFACTORED: Uses dynamic timestamps" - (test-chime-format-event-for-tooltip-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 10)) - (timestamp (test-timestamp-string time)) - (result (chime--format-event-for-tooltip - timestamp - 10 - "Team Meeting"))) - (should (stringp result)) - (should (string-match-p "Team Meeting" result)) - (should (string-match-p "02:10 PM" result)) - (should (string-match-p "10 minutes" result))) - (test-chime-format-event-for-tooltip-teardown))) - -(ert-deftest test-chime-format-event-for-tooltip-normal-hours () + (let* ((time (test-time-tomorrow-at 14 10)) + (timestamp (test-timestamp-string time)) + (result (chime--format-event-for-tooltip + timestamp + 10 + "Team Meeting"))) + (should (stringp result)) + (should (string-match-p "Team Meeting" result)) + (should (string-match-p "02:10 PM" result)) + (should (string-match-p "10 minutes" result)))) + +(chime-deftest test-chime-format-event-for-tooltip-normal-hours () "Test formatting event with hours until event. REFACTORED: Uses dynamic timestamps" - (test-chime-format-event-for-tooltip-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 15 30)) - (timestamp (test-timestamp-string time)) - (result (chime--format-event-for-tooltip - timestamp - 90 - "Afternoon Meeting"))) - (should (stringp result)) - (should (string-match-p "Afternoon Meeting" result)) - (should (string-match-p "03:30 PM" result)) - (should (string-match-p "1 hour" result))) - (test-chime-format-event-for-tooltip-teardown))) - -(ert-deftest test-chime-format-event-for-tooltip-normal-multiple-hours () + (let* ((time (test-time-tomorrow-at 15 30)) + (timestamp (test-timestamp-string time)) + (result (chime--format-event-for-tooltip + timestamp + 90 + "Afternoon Meeting"))) + (should (stringp result)) + (should (string-match-p "Afternoon Meeting" result)) + (should (string-match-p "03:30 PM" result)) + (should (string-match-p "1 hour" result)))) + +(chime-deftest test-chime-format-event-for-tooltip-normal-multiple-hours () "Test formatting event with multiple hours until event. REFACTORED: Uses dynamic timestamps" - (test-chime-format-event-for-tooltip-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 17 0)) - (timestamp (test-timestamp-string time)) - (result (chime--format-event-for-tooltip - timestamp - 300 - "End of Day Review"))) - (should (stringp result)) - (should (string-match-p "End of Day Review" result)) - (should (string-match-p "05:00 PM" result)) - (should (string-match-p "5 hours" result))) - (test-chime-format-event-for-tooltip-teardown))) + (let* ((time (test-time-tomorrow-at 17 0)) + (timestamp (test-timestamp-string time)) + (result (chime--format-event-for-tooltip + timestamp + 300 + "End of Day Review"))) + (should (stringp result)) + (should (string-match-p "End of Day Review" result)) + (should (string-match-p "05:00 PM" result)) + (should (string-match-p "5 hours" result)))) ;;; Boundary Cases -(ert-deftest test-chime-format-event-for-tooltip-boundary-exactly-one-day () +(chime-deftest test-chime-format-event-for-tooltip-boundary-exactly-one-day () "Test formatting event exactly 1 day away (1440 minutes). REFACTORED: Uses dynamic timestamps" - (test-chime-format-event-for-tooltip-setup) - (unwind-protect - (let* ((time (test-time-days-from-now 1 9 0)) - (timestamp (test-timestamp-string time)) - (result (chime--format-event-for-tooltip - timestamp - 1440 - "Tomorrow Event"))) - (should (stringp result)) - (should (string-match-p "Tomorrow Event" result)) - (should (string-match-p "09:00 AM" result)) - (should (string-match-p "in 1 day" result))) - (test-chime-format-event-for-tooltip-teardown))) - -(ert-deftest test-chime-format-event-for-tooltip-boundary-multiple-days () + (let* ((time (test-time-days-from-now 1 9 0)) + (timestamp (test-timestamp-string time)) + (result (chime--format-event-for-tooltip + timestamp + 1440 + "Tomorrow Event"))) + (should (stringp result)) + (should (string-match-p "Tomorrow Event" result)) + (should (string-match-p "09:00 AM" result)) + (should (string-match-p "in 1 day" result)))) + +(chime-deftest test-chime-format-event-for-tooltip-boundary-multiple-days () "Test formatting event multiple days away. REFACTORED: Uses dynamic timestamps" - (test-chime-format-event-for-tooltip-setup) - (unwind-protect - (let* ((time (test-time-days-from-now 3 10 0)) - (timestamp (test-timestamp-string time)) - (result (chime--format-event-for-tooltip - timestamp - 4320 ; 3 days - "Future Meeting"))) - (should (stringp result)) - (should (string-match-p "Future Meeting" result)) - (should (string-match-p "10:00 AM" result)) - (should (string-match-p "in 3 days" result))) - (test-chime-format-event-for-tooltip-teardown))) - -(ert-deftest test-chime-format-event-for-tooltip-boundary-just-under-one-day () + (let* ((time (test-time-days-from-now 3 10 0)) + (timestamp (test-timestamp-string time)) + (result (chime--format-event-for-tooltip + timestamp + 4320 ; 3 days + "Future Meeting"))) + (should (stringp result)) + (should (string-match-p "Future Meeting" result)) + (should (string-match-p "10:00 AM" result)) + (should (string-match-p "in 3 days" result)))) + +(chime-deftest test-chime-format-event-for-tooltip-boundary-just-under-one-day () "Test formatting event just under 1 day away (1439 minutes). REFACTORED: Uses dynamic timestamps" - (test-chime-format-event-for-tooltip-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 8 59)) - (timestamp (test-timestamp-string time)) - (result (chime--format-event-for-tooltip - timestamp - 1439 - "Almost Tomorrow"))) - (should (stringp result)) - (should (string-match-p "Almost Tomorrow" result)) - (should (string-match-p "08:59 AM" result)) - ;; Should show hours/minutes, not days - (should (string-match-p "23 hours" result))) - (test-chime-format-event-for-tooltip-teardown))) - -(ert-deftest test-chime-format-event-for-tooltip-boundary-zero-minutes () + (let* ((time (test-time-tomorrow-at 8 59)) + (timestamp (test-timestamp-string time)) + (result (chime--format-event-for-tooltip + timestamp + 1439 + "Almost Tomorrow"))) + (should (stringp result)) + (should (string-match-p "Almost Tomorrow" result)) + (should (string-match-p "08:59 AM" result)) + ;; Should show hours/minutes, not days + (should (string-match-p "23 hours" result)))) + +(chime-deftest test-chime-format-event-for-tooltip-boundary-zero-minutes () "Test formatting event happening right now (0 minutes). REFACTORED: Uses dynamic timestamps" - (test-chime-format-event-for-tooltip-setup) - (unwind-protect - (let* ((time (test-time-today-at 14 0)) - (timestamp (test-timestamp-string time)) - (result (chime--format-event-for-tooltip - timestamp - 0 - "Current Event"))) - (should (stringp result)) - (should (string-match-p "Current Event" result)) - (should (string-match-p "02:00 PM" result)) - (should (string-match-p "right now" result))) - (test-chime-format-event-for-tooltip-teardown))) - -(ert-deftest test-chime-format-event-for-tooltip-boundary-one-minute () + (let* ((time (test-time-today-at 14 0)) + (timestamp (test-timestamp-string time)) + (result (chime--format-event-for-tooltip + timestamp + 0 + "Current Event"))) + (should (stringp result)) + (should (string-match-p "Current Event" result)) + (should (string-match-p "02:00 PM" result)) + (should (string-match-p "right now" result)))) + +(chime-deftest test-chime-format-event-for-tooltip-boundary-one-minute () "Test formatting event 1 minute away. REFACTORED: Uses dynamic timestamps" - (test-chime-format-event-for-tooltip-setup) - (unwind-protect - (let* ((time (test-time-today-at 14 1)) - (timestamp (test-timestamp-string time)) - (result (chime--format-event-for-tooltip - timestamp - 1 - "Imminent Event"))) - (should (stringp result)) - (should (string-match-p "Imminent Event" result)) - (should (string-match-p "02:01 PM" result)) - (should (string-match-p "1 minute" result))) - (test-chime-format-event-for-tooltip-teardown))) - -(ert-deftest test-chime-format-event-for-tooltip-boundary-long-title () + (let* ((time (test-time-today-at 14 1)) + (timestamp (test-timestamp-string time)) + (result (chime--format-event-for-tooltip + timestamp + 1 + "Imminent Event"))) + (should (stringp result)) + (should (string-match-p "Imminent Event" result)) + (should (string-match-p "02:01 PM" result)) + (should (string-match-p "1 minute" result)))) + +(chime-deftest test-chime-format-event-for-tooltip-boundary-long-title () "Test formatting event with very long title. REFACTORED: Uses dynamic timestamps" - (test-chime-format-event-for-tooltip-setup) - (unwind-protect - (let* ((time (test-time-today-at 14 10)) - (timestamp (test-timestamp-string time)) - (long-title (make-string 200 ?x)) - (result (chime--format-event-for-tooltip - timestamp - 10 - long-title))) - (should (stringp result)) - (should (string-match-p long-title result))) - (test-chime-format-event-for-tooltip-teardown))) + (let* ((time (test-time-today-at 14 10)) + (timestamp (test-timestamp-string time)) + (long-title (make-string 200 ?x)) + (result (chime--format-event-for-tooltip + timestamp + 10 + long-title))) + (should (stringp result)) + (should (string-match-p long-title result)))) ;;; Error Cases -(ert-deftest test-chime-format-event-for-tooltip-error-nil-title () +(chime-deftest test-chime-format-event-for-tooltip-error-nil-title () "Test formatting with nil title doesn't crash. REFACTORED: Uses dynamic timestamps" - (test-chime-format-event-for-tooltip-setup) - (unwind-protect - (let* ((time (test-time-today-at 14 10)) - (timestamp (test-timestamp-string time))) - ;; Should not crash with nil title - (should-not (condition-case nil - (progn - (chime--format-event-for-tooltip - timestamp - 10 - nil) - nil) - (error t)))) - (test-chime-format-event-for-tooltip-teardown))) - -(ert-deftest test-chime-format-event-for-tooltip-error-empty-title () + (let* ((time (test-time-today-at 14 10)) + (timestamp (test-timestamp-string time))) + ;; Should not crash with nil title + (should-not (condition-case nil + (progn + (chime--format-event-for-tooltip + timestamp + 10 + nil) + nil) + (error t))))) + +(chime-deftest test-chime-format-event-for-tooltip-error-empty-title () "Test formatting with empty title. REFACTORED: Uses dynamic timestamps" - (test-chime-format-event-for-tooltip-setup) - (unwind-protect - (let* ((time (test-time-today-at 14 10)) - (timestamp (test-timestamp-string time)) - (result (chime--format-event-for-tooltip - timestamp - 10 - ""))) - (should (stringp result)) - (should (string-match-p "02:10 PM" result))) - (test-chime-format-event-for-tooltip-teardown))) + (let* ((time (test-time-today-at 14 10)) + (timestamp (test-timestamp-string time)) + (result (chime--format-event-for-tooltip + timestamp + 10 + ""))) + (should (stringp result)) + (should (string-match-p "02:10 PM" result)))) (provide 'test-chime-format-event-for-tooltip) ;;; test-chime-format-event-for-tooltip.el ends here diff --git a/tests/test-chime-format-refresh.el b/tests/test-chime-format-refresh.el index 0e2b58b..8393119 100644 --- a/tests/test-chime-format-refresh.el +++ b/tests/test-chime-format-refresh.el @@ -26,10 +26,6 @@ (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-format-refresh-setup () diff --git a/tests/test-chime-gather-info.el b/tests/test-chime-gather-info.el index 132f0ad..d21c06d 100644 --- a/tests/test-chime-gather-info.el +++ b/tests/test-chime-gather-info.el @@ -29,8 +29,6 @@ (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")) (require 'testutil-events (expand-file-name "testutil-events.el")) ;;; Setup and Teardown diff --git a/tests/test-chime-get-tags.el b/tests/test-chime-get-tags.el index aecd2ea..1fca101 100644 --- a/tests/test-chime-get-tags.el +++ b/tests/test-chime-get-tags.el @@ -27,9 +27,6 @@ (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -;; Load test utilities -(require 'testutil-general (expand-file-name "testutil-general.el")) - ;;;; Tests for chime--get-tags ;;; Normal Cases diff --git a/tests/test-chime-group-events-by-day.el b/tests/test-chime-group-events-by-day.el index b8546ee..277e6e1 100644 --- a/tests/test-chime-group-events-by-day.el +++ b/tests/test-chime-group-events-by-day.el @@ -38,10 +38,6 @@ (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-group-events-by-day-setup () diff --git a/tests/test-chime-has-timestamp.el b/tests/test-chime-has-timestamp.el index 1c79fb7..3e946ab 100644 --- a/tests/test-chime-has-timestamp.el +++ b/tests/test-chime-has-timestamp.el @@ -26,239 +26,171 @@ (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-has-timestamp-setup () - "Setup function run before each test." - (chime-create-test-base-dir)) - -(defun test-chime-has-timestamp-teardown () - "Teardown function run after each test." - (chime-delete-test-base-dir)) - ;;; Normal Cases -(ert-deftest test-chime-has-timestamp-standard-timestamp-with-time-returns-non-nil () +(chime-deftest test-chime-has-timestamp-standard-timestamp-with-time-returns-non-nil () "Test that standard timestamp with time returns non-nil. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 30)) - (timestamp (test-timestamp-string time)) - (result (chime--has-timestamp timestamp))) - (should result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-timestamp-without-brackets-returns-non-nil () + (let* ((time (test-time-tomorrow-at 14 30)) + (timestamp (test-timestamp-string time)) + (result (chime--has-timestamp timestamp))) + (should result))) + +(chime-deftest test-chime-has-timestamp-timestamp-without-brackets-returns-non-nil () "Test that timestamp without brackets but with time returns non-nil. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 30)) - (timestamp (format-time-string "%Y-%m-%d %a %H:%M" time)) - (result (chime--has-timestamp timestamp))) - (should result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-timestamp-with-time-range-returns-non-nil () + (let* ((time (test-time-tomorrow-at 14 30)) + (timestamp (format-time-string "%Y-%m-%d %a %H:%M" time)) + (result (chime--has-timestamp timestamp))) + (should result))) + +(chime-deftest test-chime-has-timestamp-timestamp-with-time-range-returns-non-nil () "Test that timestamp with time range returns non-nil. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 0)) - (timestamp (format-time-string "<%Y-%m-%d %a %H:%M-15:30>" time)) - (result (chime--has-timestamp timestamp))) - (should result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-scheduled-with-time-returns-non-nil () + (let* ((time (test-time-tomorrow-at 14 0)) + (timestamp (format-time-string "<%Y-%m-%d %a %H:%M-15:30>" time)) + (result (chime--has-timestamp timestamp))) + (should result))) + +(chime-deftest test-chime-has-timestamp-scheduled-with-time-returns-non-nil () "Test that SCHEDULED timestamp with time returns non-nil. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 9 0)) - (timestamp (concat "SCHEDULED: " (test-timestamp-string time))) - (result (chime--has-timestamp timestamp))) - (should result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-deadline-with-time-returns-non-nil () + (let* ((time (test-time-tomorrow-at 9 0)) + (timestamp (concat "SCHEDULED: " (test-timestamp-string time))) + (result (chime--has-timestamp timestamp))) + (should result))) + +(chime-deftest test-chime-has-timestamp-deadline-with-time-returns-non-nil () "Test that DEADLINE timestamp with time returns non-nil. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 17 0)) - (timestamp (concat "DEADLINE: " (test-timestamp-string time))) - (result (chime--has-timestamp timestamp))) - (should result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-repeater-with-time-returns-non-nil () + (let* ((time (test-time-tomorrow-at 17 0)) + (timestamp (concat "DEADLINE: " (test-timestamp-string time))) + (result (chime--has-timestamp timestamp))) + (should result))) + +(chime-deftest test-chime-has-timestamp-repeater-with-time-returns-non-nil () "Test that timestamp with repeater and time returns non-nil. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 0)) - (timestamp (format-time-string "<%Y-%m-%d %a %H:%M +1w>" time)) - (result (chime--has-timestamp timestamp))) - (should result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-midnight-timestamp-returns-non-nil () + (let* ((time (test-time-tomorrow-at 14 0)) + (timestamp (format-time-string "<%Y-%m-%d %a %H:%M +1w>" time)) + (result (chime--has-timestamp timestamp))) + (should result))) + +(chime-deftest test-chime-has-timestamp-midnight-timestamp-returns-non-nil () "Test that midnight timestamp (00:00) returns non-nil. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 0 0)) - (timestamp (test-timestamp-string time)) - (result (chime--has-timestamp timestamp))) - (should result)) - (test-chime-has-timestamp-teardown))) + (let* ((time (test-time-tomorrow-at 0 0)) + (timestamp (test-timestamp-string time)) + (result (chime--has-timestamp timestamp))) + (should result))) ;;; Boundary Cases -(ert-deftest test-chime-has-timestamp-day-wide-timestamp-returns-nil () +(chime-deftest test-chime-has-timestamp-day-wide-timestamp-returns-nil () "Test that day-wide timestamp without time returns nil. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 0 0)) - (timestamp (test-timestamp-string time t)) - (result (chime--has-timestamp timestamp))) - (should-not result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-date-only-returns-nil () + (let* ((time (test-time-tomorrow-at 0 0)) + (timestamp (test-timestamp-string time t)) + (result (chime--has-timestamp timestamp))) + (should-not result))) + +(chime-deftest test-chime-has-timestamp-date-only-returns-nil () "Test that date-only timestamp without day name returns nil. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 0 0)) - (timestamp (format-time-string "<%Y-%m-%d>" time)) - (result (chime--has-timestamp timestamp))) - (should-not result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-single-digit-hour-returns-non-nil () + (let* ((time (test-time-tomorrow-at 0 0)) + (timestamp (format-time-string "<%Y-%m-%d>" time)) + (result (chime--has-timestamp timestamp))) + (should-not result))) + +(chime-deftest test-chime-has-timestamp-single-digit-hour-returns-non-nil () "Test that timestamp with single-digit hour returns non-nil. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 9 0)) - (timestamp (format-time-string "<%Y-%m-%d %a %-H:%M>" time)) - (result (chime--has-timestamp timestamp))) - (should result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-embedded-in-text-returns-non-nil () + (let* ((time (test-time-tomorrow-at 9 0)) + (timestamp (format-time-string "<%Y-%m-%d %a %-H:%M>" time)) + (result (chime--has-timestamp timestamp))) + (should result))) + +(chime-deftest test-chime-has-timestamp-embedded-in-text-returns-non-nil () "Test that timestamp embedded in text returns non-nil. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 0)) - (timestamp (concat "Meeting scheduled for " (test-timestamp-string time) " in conference room")) - (result (chime--has-timestamp timestamp))) - (should result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-multiple-timestamps-returns-non-nil () + (let* ((time (test-time-tomorrow-at 14 0)) + (timestamp (concat "Meeting scheduled for " (test-timestamp-string time) " in conference room")) + (result (chime--has-timestamp timestamp))) + (should result))) + +(chime-deftest test-chime-has-timestamp-multiple-timestamps-returns-non-nil () "Test that string with multiple timestamps returns non-nil for first match. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time1 (test-time-tomorrow-at 14 0)) - (time2 (test-time-days-from-now 2)) - (timestamp (concat (test-timestamp-string time1) " and " - (format-time-string "<%Y-%m-%d %a %H:%M>" time2))) - (result (chime--has-timestamp timestamp))) - (should result)) - (test-chime-has-timestamp-teardown))) + (let* ((time1 (test-time-tomorrow-at 14 0)) + (time2 (test-time-days-from-now 2)) + (timestamp (concat (test-timestamp-string time1) " and " + (format-time-string "<%Y-%m-%d %a %H:%M>" time2))) + (result (chime--has-timestamp timestamp))) + (should result))) ;;; Error Cases -(ert-deftest test-chime-has-timestamp-empty-string-returns-nil () +(chime-deftest test-chime-has-timestamp-empty-string-returns-nil () "Test that empty string returns nil." - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((timestamp "") - (result (chime--has-timestamp timestamp))) - (should-not result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-nil-input-returns-nil () + (let* ((timestamp "") + (result (chime--has-timestamp timestamp))) + (should-not result))) + +(chime-deftest test-chime-has-timestamp-nil-input-returns-nil () "Test that nil input returns nil." - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((timestamp nil) - (result (chime--has-timestamp timestamp))) - (should-not result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-no-timestamp-returns-nil () + (let* ((timestamp nil) + (result (chime--has-timestamp timestamp))) + (should-not result))) + +(chime-deftest test-chime-has-timestamp-no-timestamp-returns-nil () "Test that string without timestamp returns nil." - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((timestamp "Just a regular string with no timestamp") - (result (chime--has-timestamp timestamp))) - (should-not result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-invalid-format-returns-nil () + (let* ((timestamp "Just a regular string with no timestamp") + (result (chime--has-timestamp timestamp))) + (should-not result))) + +(chime-deftest test-chime-has-timestamp-invalid-format-returns-nil () "Test that invalid timestamp format returns nil. REFACTORED: Uses dynamic timestamps (keeps invalid format for testing)" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 0)) - ;; Intentionally wrong format (MM-DD-YYYY instead of YYYY-MM-DD) for testing - (timestamp (format-time-string "<%m-%d-%Y %a %H:%M>" time)) - (result (chime--has-timestamp timestamp))) - (should-not result)) - (test-chime-has-timestamp-teardown))) - -(ert-deftest test-chime-has-timestamp-partial-timestamp-returns-nil () + (let* ((time (test-time-tomorrow-at 14 0)) + ;; Intentionally wrong format (MM-DD-YYYY instead of YYYY-MM-DD) for testing + (timestamp (format-time-string "<%m-%d-%Y %a %H:%M>" time)) + (result (chime--has-timestamp timestamp))) + (should-not result))) + +(chime-deftest test-chime-has-timestamp-partial-timestamp-returns-nil () "Test that partial timestamp returns nil. REFACTORED: Uses dynamic timestamps (keeps partial format for testing)" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 0 0)) - ;; Intentionally incomplete timestamp for testing - (timestamp (format-time-string "<%Y-%m-%d" time)) - (result (chime--has-timestamp timestamp))) - (should-not result)) - (test-chime-has-timestamp-teardown))) + (let* ((time (test-time-tomorrow-at 0 0)) + ;; Intentionally incomplete timestamp for testing + (timestamp (format-time-string "<%Y-%m-%d" time)) + (result (chime--has-timestamp timestamp))) + (should-not result))) ;;; org-gcal Integration Tests -(ert-deftest test-chime-has-timestamp-org-gcal-time-range-returns-non-nil () +(chime-deftest test-chime-has-timestamp-org-gcal-time-range-returns-non-nil () "Test that org-gcal time range format is detected. org-gcal uses format like <2025-10-24 Fri 17:30-18:00> which should be detected. REFACTORED: Uses dynamic timestamps" - (test-chime-has-timestamp-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 17 30)) - (timestamp (format-time-string "<%Y-%m-%d %a %H:%M-18:00>" time)) - (result (chime--has-timestamp timestamp))) - (should result)) - (test-chime-has-timestamp-teardown))) + (let* ((time (test-time-tomorrow-at 17 30)) + (timestamp (format-time-string "<%Y-%m-%d %a %H:%M-18:00>" time)) + (result (chime--has-timestamp timestamp))) + (should result))) (provide 'test-chime-has-timestamp) ;;; test-chime-has-timestamp.el ends here diff --git a/tests/test-chime-intervals-for-marker.el b/tests/test-chime-intervals-for-marker.el index 9b73394..295dcd5 100644 --- a/tests/test-chime-intervals-for-marker.el +++ b/tests/test-chime-intervals-for-marker.el @@ -32,7 +32,6 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-time (expand-file-name "testutil-time.el")) (require 'cl-lib) ;;; Helpers diff --git a/tests/test-chime-jump-to-event.el b/tests/test-chime-jump-to-event.el index 6db885b..29cb279 100644 --- a/tests/test-chime-jump-to-event.el +++ b/tests/test-chime-jump-to-event.el @@ -19,7 +19,6 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-general (expand-file-name "testutil-general.el")) (defun test-chime-jump-to-event--make-temp-org-file (content) "Write CONTENT to a temp .org file under the test base dir and return its path." diff --git a/tests/test-chime-make-tooltip.el b/tests/test-chime-make-tooltip.el index 7ace684..6b704b1 100644 --- a/tests/test-chime-make-tooltip.el +++ b/tests/test-chime-make-tooltip.el @@ -28,8 +28,6 @@ (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")) (require 'testutil-events (expand-file-name "testutil-events.el")) ;;; Setup and Teardown diff --git a/tests/test-chime-modeline-faces.el b/tests/test-chime-modeline-faces.el index dc8eae8..27c180a 100644 --- a/tests/test-chime-modeline-faces.el +++ b/tests/test-chime-modeline-faces.el @@ -29,8 +29,6 @@ (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-general (expand-file-name "testutil-general.el")) -(require 'testutil-time (expand-file-name "testutil-time.el")) (require 'testutil-events (expand-file-name "testutil-events.el")) ;;; Setup/Teardown diff --git a/tests/test-chime-modeline-no-events-text.el b/tests/test-chime-modeline-no-events-text.el index f64c71f..eaf0633 100644 --- a/tests/test-chime-modeline-no-events-text.el +++ b/tests/test-chime-modeline-no-events-text.el @@ -31,10 +31,6 @@ (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 (defvar test-chime-modeline-no-events-text--orig-lookahead nil) diff --git a/tests/test-chime-modeline.el b/tests/test-chime-modeline.el index 63ba26c..27a1936 100644 --- a/tests/test-chime-modeline.el +++ b/tests/test-chime-modeline.el @@ -30,8 +30,6 @@ (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")) (require 'testutil-events (expand-file-name "testutil-events.el")) ;;; Setup and Teardown 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 diff --git a/tests/test-chime-notification-text.el b/tests/test-chime-notification-text.el index a707d29..7363cd2 100644 --- a/tests/test-chime-notification-text.el +++ b/tests/test-chime-notification-text.el @@ -26,10 +26,6 @@ (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-text-setup () diff --git a/tests/test-chime-notifications.el b/tests/test-chime-notifications.el index 17ce540..e3c7cc2 100644 --- a/tests/test-chime-notifications.el +++ b/tests/test-chime-notifications.el @@ -26,221 +26,177 @@ (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-notifications-setup () - "Setup function run before each test." - (chime-create-test-base-dir)) - -(defun test-chime-notifications-teardown () - "Teardown function run after each test." - (chime-delete-test-base-dir)) - ;;; Normal Cases -(ert-deftest test-chime-notifications-single-time-single-interval-returns-pair () +(chime-deftest test-chime-notifications-single-time-single-interval-returns-pair () "Test that single time with single interval returns one notification pair. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Event at 14:10 (10 minutes from now) - (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 return list with one pair - (should (listp result)) - (should (= 1 (length result)))))) - (test-chime-notifications-teardown))) - -(ert-deftest test-chime-notifications-single-time-multiple-intervals-returns-multiple-pairs () + (let* ((now (test-time-today-at 14 0)) + ;; Event at 14:10 (10 minutes from now) + (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 return list with one pair + (should (listp result)) + (should (= 1 (length result))))))) + +(chime-deftest test-chime-notifications-single-time-multiple-intervals-returns-multiple-pairs () "Test that single time with multiple intervals returns multiple notification pairs. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Event at 14:10 - (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) (5 . medium))))) ; Two intervals, only 10 matches - (result (chime--notifications event))) - ;; Should return only matching interval - (should (listp result)) - (should (= 1 (length result)))))) - (test-chime-notifications-teardown))) - -(ert-deftest test-chime-notifications-multiple-times-single-interval-returns-matching-pairs () + (let* ((now (test-time-today-at 14 0)) + ;; Event at 14:10 + (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) (5 . medium))))) ; Two intervals, only 10 matches + (result (chime--notifications event))) + ;; Should return only matching interval + (should (listp result)) + (should (= 1 (length result))))))) + +(chime-deftest test-chime-notifications-multiple-times-single-interval-returns-matching-pairs () "Test that multiple times with single interval returns matching notifications. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Two events: one at 14:10, one at 14:05 - (event-time-1 (test-time-today-at 14 10)) - (event-time-2 (test-time-today-at 14 5)) - (timestamp-str-1 (test-timestamp-string event-time-1)) - (timestamp-str-2 (test-timestamp-string event-time-2))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str-1 . ,event-time-1) - (,timestamp-str-2 . ,event-time-2))) - (title . "Test Event") - (intervals . ((10 . medium))))) ; Only first time matches - (result (chime--notifications event))) - ;; Should return only matching time - (should (listp result)) - (should (= 1 (length result)))))) - (test-chime-notifications-teardown))) - -(ert-deftest test-chime-notifications-multiple-times-multiple-intervals-returns-all-matches () + (let* ((now (test-time-today-at 14 0)) + ;; Two events: one at 14:10, one at 14:05 + (event-time-1 (test-time-today-at 14 10)) + (event-time-2 (test-time-today-at 14 5)) + (timestamp-str-1 (test-timestamp-string event-time-1)) + (timestamp-str-2 (test-timestamp-string event-time-2))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str-1 . ,event-time-1) + (,timestamp-str-2 . ,event-time-2))) + (title . "Test Event") + (intervals . ((10 . medium))))) ; Only first time matches + (result (chime--notifications event))) + ;; Should return only matching time + (should (listp result)) + (should (= 1 (length result))))))) + +(chime-deftest test-chime-notifications-multiple-times-multiple-intervals-returns-all-matches () "Test that multiple times and intervals return all matching combinations. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Event at 14:10 and 14:05 - (event-time-1 (test-time-today-at 14 10)) - (event-time-2 (test-time-today-at 14 5)) - (timestamp-str-1 (test-timestamp-string event-time-1)) - (timestamp-str-2 (test-timestamp-string event-time-2))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str-1 . ,event-time-1) - (,timestamp-str-2 . ,event-time-2))) - (title . "Test Event") - (intervals . ((10 . medium) (5 . medium))))) ; Both match (10 with first, 5 with second) - (result (chime--notifications event))) - ;; Should return both matching pairs - (should (listp result)) - (should (= 2 (length result)))))) - (test-chime-notifications-teardown))) - -(ert-deftest test-chime-notifications-zero-interval-returns-current-time-match () + (let* ((now (test-time-today-at 14 0)) + ;; Event at 14:10 and 14:05 + (event-time-1 (test-time-today-at 14 10)) + (event-time-2 (test-time-today-at 14 5)) + (timestamp-str-1 (test-timestamp-string event-time-1)) + (timestamp-str-2 (test-timestamp-string event-time-2))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str-1 . ,event-time-1) + (,timestamp-str-2 . ,event-time-2))) + (title . "Test Event") + (intervals . ((10 . medium) (5 . medium))))) ; Both match (10 with first, 5 with second) + (result (chime--notifications event))) + ;; Should return both matching pairs + (should (listp result)) + (should (= 2 (length result))))))) + +(chime-deftest test-chime-notifications-zero-interval-returns-current-time-match () "Test that zero interval (notify now) works correctly. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Event at exactly current time - (event-time (test-time-today-at 14 0)) - (timestamp-str (test-timestamp-string event-time))) - (with-test-time now - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Test Event") - (intervals . ((0 . high))))) - (result (chime--notifications event))) - ;; Should return one matching pair - (should (listp result)) - (should (= 1 (length result)))))) - (test-chime-notifications-teardown))) - -(ert-deftest test-chime-notifications-filters-day-wide-events () + (let* ((now (test-time-today-at 14 0)) + ;; Event at exactly current time + (event-time (test-time-today-at 14 0)) + (timestamp-str (test-timestamp-string event-time))) + (with-test-time now + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Test Event") + (intervals . ((0 . high))))) + (result (chime--notifications event))) + ;; Should return one matching pair + (should (listp result)) + (should (= 1 (length result))))))) + +(chime-deftest test-chime-notifications-filters-day-wide-events () "Test that day-wide events (without time) are filtered out. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Mix of day-wide and timed events - (event-time (test-time-today-at 14 10)) - (timestamp-str-day (test-timestamp-string event-time t)) ; Day-wide - (timestamp-str-timed (test-timestamp-string event-time))) ; Timed - (with-test-time now - (let* ((event `((times . ((,timestamp-str-day . ,event-time) ; Day-wide - (,timestamp-str-timed . ,event-time))) ; Timed - (title . "Test Event") - (intervals . ((10 . medium))))) - (result (chime--notifications event))) - ;; Should return only timed event - (should (listp result)) - (should (= 1 (length result)))))) - (test-chime-notifications-teardown))) + (let* ((now (test-time-today-at 14 0)) + ;; Mix of day-wide and timed events + (event-time (test-time-today-at 14 10)) + (timestamp-str-day (test-timestamp-string event-time t)) ; Day-wide + (timestamp-str-timed (test-timestamp-string event-time))) ; Timed + (with-test-time now + (let* ((event `((times . ((,timestamp-str-day . ,event-time) ; Day-wide + (,timestamp-str-timed . ,event-time))) ; Timed + (title . "Test Event") + (intervals . ((10 . medium))))) + (result (chime--notifications event))) + ;; Should return only timed event + (should (listp result)) + (should (= 1 (length result))))))) ;;; Boundary Cases -(ert-deftest test-chime-notifications-empty-times-returns-empty-list () +(chime-deftest test-chime-notifications-empty-times-returns-empty-list () "Test that event with no times returns empty list. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-notifications-setup) - (unwind-protect - (let ((now (test-time-today-at 14 0))) - (with-test-time now - (let* ((event `((times . (())) - (title . "Test Event") - (intervals . ((10 . medium))))) - (result (chime--notifications event))) - (should (listp result)) - (should (= 0 (length result)))))) - (test-chime-notifications-teardown))) - -(ert-deftest test-chime-notifications-empty-intervals-returns-empty-list () + (let ((now (test-time-today-at 14 0))) + (with-test-time now + (let* ((event `((times . (())) + (title . "Test Event") + (intervals . ((10 . medium))))) + (result (chime--notifications event))) + (should (listp result)) + (should (= 0 (length result))))))) + +(chime-deftest test-chime-notifications-empty-intervals-returns-empty-list () "Test that event with no intervals returns empty list. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-notifications-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 . ()))) - (result (chime--notifications event))) - (should (listp result)) - (should (= 0 (length result)))))) - (test-chime-notifications-teardown))) + (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 . ()))) + (result (chime--notifications event))) + (should (listp result)) + (should (= 0 (length result))))))) ;;; Error Cases -(ert-deftest test-chime-notifications-nil-times-returns-empty-list () +(chime-deftest test-chime-notifications-nil-times-returns-empty-list () "Test that event with nil times returns empty list. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-notifications-setup) - (unwind-protect - (let ((now (test-time-today-at 14 0))) - (with-test-time now - (let* ((event `((times . (nil)) - (title . "Test Event") - (intervals . ((10 . medium))))) - (result (chime--notifications event))) - (should (listp result)) - (should (= 0 (length result)))))) - (test-chime-notifications-teardown))) - -(ert-deftest test-chime-notifications-nil-intervals-returns-empty-list () + (let ((now (test-time-today-at 14 0))) + (with-test-time now + (let* ((event `((times . (nil)) + (title . "Test Event") + (intervals . ((10 . medium))))) + (result (chime--notifications event))) + (should (listp result)) + (should (= 0 (length result))))))) + +(chime-deftest test-chime-notifications-nil-intervals-returns-empty-list () "Test that event with nil intervals returns empty list. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-notifications-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 . nil))) - (result (chime--notifications event))) - (should (listp result)) - (should (= 0 (length result)))))) - (test-chime-notifications-teardown))) + (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 . nil))) + (result (chime--notifications event))) + (should (listp result)) + (should (= 0 (length result))))))) (provide 'test-chime-notifications) ;;; test-chime-notifications.el ends here diff --git a/tests/test-chime-notify.el b/tests/test-chime-notify.el index cd7b350..0b77993 100644 --- a/tests/test-chime-notify.el +++ b/tests/test-chime-notify.el @@ -26,9 +26,6 @@ (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -;; Load test utilities -(require 'testutil-general (expand-file-name "testutil-general.el")) - ;;; Setup and Teardown (defun test-chime-notify-setup () diff --git a/tests/test-chime-overdue-todos.el b/tests/test-chime-overdue-todos.el index 84bc091..32e50c3 100644 --- a/tests/test-chime-overdue-todos.el +++ b/tests/test-chime-overdue-todos.el @@ -31,10 +31,6 @@ (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")) - ;;; Test Helper Functions (defun test-overdue--create-event (title timestamp has-time) @@ -47,19 +43,9 @@ HAS-TIME determines if timestamp has time component." (times . ,times) (intervals . (10))))) -;;; Setup and Teardown - -(defun test-chime-overdue-setup () - "Setup function run before each test." - (chime-create-test-base-dir)) - -(defun test-chime-overdue-teardown () - "Teardown function run after each test." - (chime-delete-test-base-dir)) - ;;; Tests for chime--event-has-any-passed-time -(ert-deftest test-overdue-has-passed-time-yesterday-all-day () +(chime-deftest test-overdue-has-passed-time-yesterday-all-day () "Test that all-day event from yesterday is recognized as passed. TIME RELATIONSHIPS: @@ -70,20 +56,17 @@ EXPECTED BEHAVIOR: Should return t (yesterday is in the past) REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-now)) - (yesterday (test-time-yesterday-at 0 0)) - (yesterday-timestamp (test-timestamp-string yesterday t)) - (event (test-overdue--create-event - "Yesterday Event" - yesterday-timestamp - nil))) ; all-day event - (with-test-time now - (should (chime--event-has-any-passed-time event)))) - (test-chime-overdue-teardown))) - -(ert-deftest test-overdue-has-passed-time-today-all-day () + (let* ((now (test-time-now)) + (yesterday (test-time-yesterday-at 0 0)) + (yesterday-timestamp (test-timestamp-string yesterday t)) + (event (test-overdue--create-event + "Yesterday Event" + yesterday-timestamp + nil))) ; all-day event + (with-test-time now + (should (chime--event-has-any-passed-time event))))) + +(chime-deftest test-overdue-has-passed-time-today-all-day () "Test that all-day event from today is recognized as passed. TIME RELATIONSHIPS: @@ -111,19 +94,16 @@ REFACTORING NOTES: Simple case - just needs TODAY timestamp and TODAY current-time. REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-now)) - (today-timestamp (test-timestamp-string now t)) - (event (test-overdue--create-event - "Today Event" - today-timestamp - nil))) ; all-day event - (with-test-time now - (should (chime--event-has-any-passed-time event)))) - (test-chime-overdue-teardown))) - -(ert-deftest test-overdue-has-passed-time-tomorrow-all-day () + (let* ((now (test-time-now)) + (today-timestamp (test-timestamp-string now t)) + (event (test-overdue--create-event + "Today Event" + today-timestamp + nil))) ; all-day event + (with-test-time now + (should (chime--event-has-any-passed-time event))))) + +(chime-deftest test-overdue-has-passed-time-tomorrow-all-day () "Test that all-day event from tomorrow is NOT recognized as passed. TIME RELATIONSHIPS: @@ -134,20 +114,17 @@ EXPECTED BEHAVIOR: Should return nil (tomorrow is in the future) REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-now)) - (tomorrow (test-time-tomorrow-at 0 0)) - (tomorrow-timestamp (test-timestamp-string tomorrow t)) - (event (test-overdue--create-event - "Tomorrow Event" - tomorrow-timestamp - nil))) ; all-day event - (with-test-time now - (should-not (chime--event-has-any-passed-time event)))) - (test-chime-overdue-teardown))) - -(ert-deftest test-overdue-has-passed-time-timed-event-past () + (let* ((now (test-time-now)) + (tomorrow (test-time-tomorrow-at 0 0)) + (tomorrow-timestamp (test-timestamp-string tomorrow t)) + (event (test-overdue--create-event + "Tomorrow Event" + tomorrow-timestamp + nil))) ; all-day event + (with-test-time now + (should-not (chime--event-has-any-passed-time event))))) + +(chime-deftest test-overdue-has-passed-time-timed-event-past () "Test that timed event in the past is recognized as passed. TIME RELATIONSHIPS: @@ -158,20 +135,17 @@ EXPECTED BEHAVIOR: Should return t (event time has passed) REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - (past-event (test-time-today-at 9 0)) - (past-timestamp (test-timestamp-string past-event)) - (event (test-overdue--create-event - "Past Meeting" - past-timestamp - t))) ; timed event - (with-test-time now - (should (chime--event-has-any-passed-time event)))) - (test-chime-overdue-teardown))) - -(ert-deftest test-overdue-has-passed-time-timed-event-future () + (let* ((now (test-time-today-at 14 0)) + (past-event (test-time-today-at 9 0)) + (past-timestamp (test-timestamp-string past-event)) + (event (test-overdue--create-event + "Past Meeting" + past-timestamp + t))) ; timed event + (with-test-time now + (should (chime--event-has-any-passed-time event))))) + +(chime-deftest test-overdue-has-passed-time-timed-event-future () "Test that timed event in the future is NOT recognized as passed. TIME RELATIONSHIPS: @@ -182,22 +156,19 @@ EXPECTED BEHAVIOR: Should return nil (event time is in future) REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - (future-event (test-time-today-at 16 0)) - (future-timestamp (test-timestamp-string future-event)) - (event (test-overdue--create-event - "Future Meeting" - future-timestamp - t))) ; timed event - (with-test-time now - (should-not (chime--event-has-any-passed-time event)))) - (test-chime-overdue-teardown))) + (let* ((now (test-time-today-at 14 0)) + (future-event (test-time-today-at 16 0)) + (future-timestamp (test-timestamp-string future-event)) + (event (test-overdue--create-event + "Future Meeting" + future-timestamp + t))) ; timed event + (with-test-time now + (should-not (chime--event-has-any-passed-time event))))) ;;; Tests for chime--display-as-day-wide-event with overdue setting -(ert-deftest test-overdue-display-yesterday-all-day-with-overdue-enabled () +(chime-deftest test-overdue-display-yesterday-all-day-with-overdue-enabled () "Test that yesterday's all-day event is displayed when overdue is enabled. TIME RELATIONSHIPS: @@ -209,133 +180,115 @@ EXPECTED BEHAVIOR: Should display (overdue enabled shows past events) REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-now)) - (yesterday (test-time-yesterday-at 0 0)) - (yesterday-timestamp (test-timestamp-string yesterday t)) - (chime-show-any-overdue-with-day-wide-alerts t) - (chime-day-wide-advance-notice nil) - (event (test-overdue--create-event - "Yesterday Birthday" - yesterday-timestamp - nil))) - (with-test-time now - (should (chime--display-as-day-wide-event event)))) - (test-chime-overdue-teardown))) - -(ert-deftest test-overdue-display-yesterday-all-day-with-overdue-disabled () + (let* ((now (test-time-now)) + (yesterday (test-time-yesterday-at 0 0)) + (yesterday-timestamp (test-timestamp-string yesterday t)) + (chime-show-any-overdue-with-day-wide-alerts t) + (chime-day-wide-advance-notice nil) + (event (test-overdue--create-event + "Yesterday Birthday" + yesterday-timestamp + nil))) + (with-test-time now + (should (chime--display-as-day-wide-event event))))) + +(chime-deftest test-overdue-display-yesterday-all-day-with-overdue-disabled () "Test that yesterday's all-day event is NOT displayed when overdue is disabled. This prevents showing old birthdays/holidays from the past. REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-now)) - (yesterday (test-time-yesterday-at 0 0)) - (yesterday-timestamp (test-timestamp-string yesterday t)) - (chime-show-any-overdue-with-day-wide-alerts nil) - (chime-day-wide-advance-notice nil) - (event (test-overdue--create-event - "Yesterday Birthday" - yesterday-timestamp - nil))) - (with-test-time now - (should-not (chime--display-as-day-wide-event event)))) - (test-chime-overdue-teardown))) - -(ert-deftest test-overdue-display-yesterday-timed-with-overdue-enabled () + (let* ((now (test-time-now)) + (yesterday (test-time-yesterday-at 0 0)) + (yesterday-timestamp (test-timestamp-string yesterday t)) + (chime-show-any-overdue-with-day-wide-alerts nil) + (chime-day-wide-advance-notice nil) + (event (test-overdue--create-event + "Yesterday Birthday" + yesterday-timestamp + nil))) + (with-test-time now + (should-not (chime--display-as-day-wide-event event))))) + +(chime-deftest test-overdue-display-yesterday-timed-with-overdue-enabled () "Test that yesterday's timed event is displayed when overdue is enabled. TIME: TODAY 10am, Event: YESTERDAY 2pm, overdue=t EXPECTED: Display (show past timed events when enabled) REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-now)) - (yesterday (test-time-yesterday-at 14 0)) - (yesterday-timestamp (test-timestamp-string yesterday)) - (chime-show-any-overdue-with-day-wide-alerts t) - (chime-day-wide-advance-notice nil) - (event (test-overdue--create-event - "Yesterday Meeting" - yesterday-timestamp - t))) - (with-test-time now - (should (chime--display-as-day-wide-event event)))) - (test-chime-overdue-teardown))) - -(ert-deftest test-overdue-display-yesterday-timed-with-overdue-disabled () + (let* ((now (test-time-now)) + (yesterday (test-time-yesterday-at 14 0)) + (yesterday-timestamp (test-timestamp-string yesterday)) + (chime-show-any-overdue-with-day-wide-alerts t) + (chime-day-wide-advance-notice nil) + (event (test-overdue--create-event + "Yesterday Meeting" + yesterday-timestamp + t))) + (with-test-time now + (should (chime--display-as-day-wide-event event))))) + +(chime-deftest test-overdue-display-yesterday-timed-with-overdue-disabled () "Test that yesterday's timed event is NOT displayed when overdue is disabled. TIME: TODAY 10am, Event: YESTERDAY 2pm, overdue=nil EXPECTED: Hide (don't show past timed events when disabled) REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-now)) - (yesterday (test-time-yesterday-at 14 0)) - (yesterday-timestamp (test-timestamp-string yesterday)) - (chime-show-any-overdue-with-day-wide-alerts nil) - (chime-day-wide-advance-notice nil) - (event (test-overdue--create-event - "Yesterday Meeting" - yesterday-timestamp - t))) - (with-test-time now - (should-not (chime--display-as-day-wide-event event)))) - (test-chime-overdue-teardown))) - -(ert-deftest test-overdue-display-today-all-day-always-shown () + (let* ((now (test-time-now)) + (yesterday (test-time-yesterday-at 14 0)) + (yesterday-timestamp (test-timestamp-string yesterday)) + (chime-show-any-overdue-with-day-wide-alerts nil) + (chime-day-wide-advance-notice nil) + (event (test-overdue--create-event + "Yesterday Meeting" + yesterday-timestamp + t))) + (with-test-time now + (should-not (chime--display-as-day-wide-event event))))) + +(chime-deftest test-overdue-display-today-all-day-always-shown () "Test that today's all-day event is always displayed regardless of overdue setting. TIME: TODAY 10am, Event: TODAY (all-day), both overdue=t and =nil EXPECTED: Always display (today's events shown regardless of setting) REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-now)) - (today-timestamp (test-timestamp-string now t)) - (chime-day-wide-advance-notice nil) - (event (test-overdue--create-event - "Today Birthday" - today-timestamp - nil))) - (with-test-time now - ;; Should show with overdue enabled - (let ((chime-show-any-overdue-with-day-wide-alerts t)) - (should (chime--display-as-day-wide-event event))) - ;; Should also show with overdue disabled (it's today, not overdue) - (let ((chime-show-any-overdue-with-day-wide-alerts nil)) - (should (chime--display-as-day-wide-event event))))) - (test-chime-overdue-teardown))) - -(ert-deftest test-overdue-display-week-old-all-day-with-overdue-enabled () + (let* ((now (test-time-now)) + (today-timestamp (test-timestamp-string now t)) + (chime-day-wide-advance-notice nil) + (event (test-overdue--create-event + "Today Birthday" + today-timestamp + nil))) + (with-test-time now + ;; Should show with overdue enabled + (let ((chime-show-any-overdue-with-day-wide-alerts t)) + (should (chime--display-as-day-wide-event event))) + ;; Should also show with overdue disabled (it's today, not overdue) + (let ((chime-show-any-overdue-with-day-wide-alerts nil)) + (should (chime--display-as-day-wide-event event)))))) + +(chime-deftest test-overdue-display-week-old-all-day-with-overdue-enabled () "Test that week-old all-day event is displayed when overdue is enabled. TIME: TODAY (Oct 28), Event: 7 DAYS AGO (Oct 21), overdue=t EXPECTED: Display (show old events when enabled) REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-now)) - (week-ago (test-time-days-ago 7)) - (week-ago-timestamp (test-timestamp-string week-ago t)) - (chime-show-any-overdue-with-day-wide-alerts t) - (chime-day-wide-advance-notice nil) - (event (test-overdue--create-event - "Week Old Event" - week-ago-timestamp - nil))) - (with-test-time now - (should (chime--display-as-day-wide-event event)))) - (test-chime-overdue-teardown))) - -(ert-deftest test-overdue-display-week-old-all-day-with-overdue-disabled () + (let* ((now (test-time-now)) + (week-ago (test-time-days-ago 7)) + (week-ago-timestamp (test-timestamp-string week-ago t)) + (chime-show-any-overdue-with-day-wide-alerts t) + (chime-day-wide-advance-notice nil) + (event (test-overdue--create-event + "Week Old Event" + week-ago-timestamp + nil))) + (with-test-time now + (should (chime--display-as-day-wide-event event))))) + +(chime-deftest test-overdue-display-week-old-all-day-with-overdue-disabled () "Test that week-old all-day event is NOT displayed when overdue is disabled. This prevents showing old birthdays/holidays from past weeks. @@ -343,48 +296,42 @@ TIME: TODAY (Oct 28), Event: 7 DAYS AGO (Oct 21), overdue=nil EXPECTED: Hide (prevent old birthday spam) REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-now)) - (week-ago (test-time-days-ago 7)) - (week-ago-timestamp (test-timestamp-string week-ago t)) - (chime-show-any-overdue-with-day-wide-alerts nil) - (chime-day-wide-advance-notice nil) - (event (test-overdue--create-event - "Week Old Event" - week-ago-timestamp - nil))) - (with-test-time now - (should-not (chime--display-as-day-wide-event event)))) - (test-chime-overdue-teardown))) + (let* ((now (test-time-now)) + (week-ago (test-time-days-ago 7)) + (week-ago-timestamp (test-timestamp-string week-ago t)) + (chime-show-any-overdue-with-day-wide-alerts nil) + (chime-day-wide-advance-notice nil) + (event (test-overdue--create-event + "Week Old Event" + week-ago-timestamp + nil))) + (with-test-time now + (should-not (chime--display-as-day-wide-event event))))) ;;; Tests verifying overdue doesn't affect future events -(ert-deftest test-overdue-future-event-not-affected-by-overdue-setting () +(chime-deftest test-overdue-future-event-not-affected-by-overdue-setting () "Test that future events are not affected by overdue setting. TIME: TODAY (Oct 28), Event: 2 DAYS FROM NOW (Oct 30), both overdue settings EXPECTED: Never display (future events not shown without advance notice) REFACTORED: Uses dynamic timestamps via testutil-time.el" - (test-chime-overdue-setup) - (unwind-protect - (let* ((now (test-time-now)) - (future (test-time-days-from-now 2)) - (future-timestamp (test-timestamp-string future t)) - (chime-day-wide-advance-notice nil) - (event (test-overdue--create-event - "Future Event" - future-timestamp - nil))) - (with-test-time now - ;; Should NOT show with overdue enabled (it's future, not today) - (let ((chime-show-any-overdue-with-day-wide-alerts t)) - (should-not (chime--display-as-day-wide-event event))) - ;; Should NOT show with overdue disabled (it's future, not today) - (let ((chime-show-any-overdue-with-day-wide-alerts nil)) - (should-not (chime--display-as-day-wide-event event))))) - (test-chime-overdue-teardown))) + (let* ((now (test-time-now)) + (future (test-time-days-from-now 2)) + (future-timestamp (test-timestamp-string future t)) + (chime-day-wide-advance-notice nil) + (event (test-overdue--create-event + "Future Event" + future-timestamp + nil))) + (with-test-time now + ;; Should NOT show with overdue enabled (it's future, not today) + (let ((chime-show-any-overdue-with-day-wide-alerts t)) + (should-not (chime--display-as-day-wide-event event))) + ;; Should NOT show with overdue disabled (it's future, not today) + (let ((chime-show-any-overdue-with-day-wide-alerts nil)) + (should-not (chime--display-as-day-wide-event event)))))) (provide 'test-chime-overdue-todos) ;;; test-chime-overdue-todos.el ends here diff --git a/tests/test-chime-process-notifications.el b/tests/test-chime-process-notifications.el index 75cac9b..1a93842 100644 --- a/tests/test-chime-process-notifications.el +++ b/tests/test-chime-process-notifications.el @@ -26,363 +26,310 @@ (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-process-notifications-setup () - "Setup function run before each test." - (chime-create-test-base-dir)) - -(defun test-chime-process-notifications-teardown () - "Teardown function run after each test." - (chime-delete-test-base-dir)) - ;;; Normal Cases -(ert-deftest test-chime-process-notifications-normal-single-event-calls-notify () +(chime-deftest test-chime-process-notifications-normal-single-event-calls-notify () "Test that single event with notification calls chime--notify. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-process-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Event at 14:10 (10 minutes from now) - (event-time (test-time-today-at 14 10)) - (timestamp-str (test-timestamp-string event-time)) - (notify-called nil) - (notify-messages '())) - (with-test-time now - (cl-letf (((symbol-function 'chime--notify) - (lambda (msg) - (setq notify-called t) - (push msg notify-messages))) - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () nil))) - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Team Meeting") - (intervals . ((10 . medium))))) - (events (list event))) - (chime--process-notifications events) - ;; Should call notify - (should notify-called) - (should (= 1 (length notify-messages))) - (should (string-match-p "Team Meeting" (caar notify-messages))))))) - (test-chime-process-notifications-teardown))) - -(ert-deftest test-chime-process-notifications-normal-multiple-events-calls-notify-multiple-times () + (let* ((now (test-time-today-at 14 0)) + ;; Event at 14:10 (10 minutes from now) + (event-time (test-time-today-at 14 10)) + (timestamp-str (test-timestamp-string event-time)) + (notify-called nil) + (notify-messages '())) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) + (setq notify-called t) + (push msg notify-messages))) + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () nil))) + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Team Meeting") + (intervals . ((10 . medium))))) + (events (list event))) + (chime--process-notifications events) + ;; Should call notify + (should notify-called) + (should (= 1 (length notify-messages))) + (should (string-match-p "Team Meeting" (caar notify-messages)))))))) + +(chime-deftest test-chime-process-notifications-normal-multiple-events-calls-notify-multiple-times () "Test that multiple events with notifications call chime--notify multiple times. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-process-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Event 1 at 14:10 - (event-time-1 (test-time-today-at 14 10)) - (timestamp-str-1 (test-timestamp-string event-time-1)) - ;; Event 2 at 14:05 - (event-time-2 (test-time-today-at 14 5)) - (timestamp-str-2 (test-timestamp-string event-time-2)) - (notify-count 0)) - (with-test-time now - (cl-letf (((symbol-function 'chime--notify) - (lambda (msg) (setq notify-count (1+ notify-count)))) - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () nil))) - (let* ((event1 `((times . ((,timestamp-str-1 . ,event-time-1))) - (title . "Meeting 1") - (intervals . ((10 . medium))))) - (event2 `((times . ((,timestamp-str-2 . ,event-time-2))) - (title . "Meeting 2") - (intervals . ((5 . medium))))) - (events (list event1 event2))) - (chime--process-notifications events) - ;; Should call notify twice (once per event) - (should (= 2 notify-count)))))) - (test-chime-process-notifications-teardown))) - -(ert-deftest test-chime-process-notifications-normal-deduplication-removes-duplicates () + (let* ((now (test-time-today-at 14 0)) + ;; Event 1 at 14:10 + (event-time-1 (test-time-today-at 14 10)) + (timestamp-str-1 (test-timestamp-string event-time-1)) + ;; Event 2 at 14:05 + (event-time-2 (test-time-today-at 14 5)) + (timestamp-str-2 (test-timestamp-string event-time-2)) + (notify-count 0)) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) (setq notify-count (1+ notify-count)))) + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () nil))) + (let* ((event1 `((times . ((,timestamp-str-1 . ,event-time-1))) + (title . "Meeting 1") + (intervals . ((10 . medium))))) + (event2 `((times . ((,timestamp-str-2 . ,event-time-2))) + (title . "Meeting 2") + (intervals . ((5 . medium))))) + (events (list event1 event2))) + (chime--process-notifications events) + ;; Should call notify twice (once per event) + (should (= 2 notify-count))))))) + +(chime-deftest test-chime-process-notifications-normal-deduplication-removes-duplicates () "Test that duplicate notification messages are deduplicated. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-process-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Two events with same title and time - should dedupe - (event-time (test-time-today-at 14 10)) - (timestamp-str (test-timestamp-string event-time)) - (notify-messages '())) - (with-test-time now - (cl-letf (((symbol-function 'chime--notify) - (lambda (msg) (push msg notify-messages))) - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () nil))) - (let* ((event1 `((times . ((,timestamp-str . ,event-time))) - (title . "Team Meeting") - (intervals . ((10 . medium))))) - (event2 `((times . ((,timestamp-str . ,event-time))) - (title . "Team Meeting") - (intervals . ((10 . medium))))) - (events (list event1 event2))) - (chime--process-notifications events) - ;; Should only call notify once due to deduplication - (should (= 1 (length notify-messages))))))) - (test-chime-process-notifications-teardown))) - -(ert-deftest test-chime-process-notifications-normal-day-wide-notifications-called-at-right-time () + (let* ((now (test-time-today-at 14 0)) + ;; Two events with same title and time - should dedupe + (event-time (test-time-today-at 14 10)) + (timestamp-str (test-timestamp-string event-time)) + (notify-messages '())) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) (push msg notify-messages))) + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () nil))) + (let* ((event1 `((times . ((,timestamp-str . ,event-time))) + (title . "Team Meeting") + (intervals . ((10 . medium))))) + (event2 `((times . ((,timestamp-str . ,event-time))) + (title . "Team Meeting") + (intervals . ((10 . medium))))) + (events (list event1 event2))) + (chime--process-notifications events) + ;; Should only call notify once due to deduplication + (should (= 1 (length notify-messages)))))))) + +(chime-deftest test-chime-process-notifications-normal-day-wide-notifications-called-at-right-time () "Test that day-wide notifications are sent when current time matches. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-process-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 9 0)) - ;; Day-wide event - (event-time (test-time-today-at 0 0)) - (timestamp-str (test-timestamp-string event-time t)) ; Day-wide - (notify-count 0)) - (with-test-time now - (cl-letf (((symbol-function 'chime--notify) - (lambda (msg) (setq notify-count (1+ notify-count)))) - ;; Mock day-wide time to return true - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () t)) - ((symbol-function 'chime--day-wide-notifications) - (lambda (events) (list "Day-wide alert")))) - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "All Day Event") - (intervals . ()))) - (events (list event))) - (chime--process-notifications events) - ;; Should call notify at least once for day-wide - (should (>= notify-count 1)))))) - (test-chime-process-notifications-teardown))) - -(ert-deftest test-chime-process-notifications-normal-no-day-wide-when-wrong-time () + (let* ((now (test-time-today-at 9 0)) + ;; Day-wide event + (event-time (test-time-today-at 0 0)) + (timestamp-str (test-timestamp-string event-time t)) ; Day-wide + (notify-count 0)) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) (setq notify-count (1+ notify-count)))) + ;; Mock day-wide time to return true + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () t)) + ((symbol-function 'chime--day-wide-notifications) + (lambda (events) (list "Day-wide alert")))) + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "All Day Event") + (intervals . ()))) + (events (list event))) + (chime--process-notifications events) + ;; Should call notify at least once for day-wide + (should (>= notify-count 1))))))) + +(chime-deftest test-chime-process-notifications-normal-no-day-wide-when-wrong-time () "Test that day-wide notifications are not sent when time doesn't match. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-process-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - (event-time (test-time-today-at 0 0)) - (timestamp-str (test-timestamp-string event-time t)) ; Day-wide - (day-wide-called nil)) - (with-test-time now - (cl-letf (((symbol-function 'chime--notify) (lambda (msg) nil)) - ;; Mock day-wide time to return false - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () nil)) - ((symbol-function 'chime--day-wide-notifications) - (lambda (events) - (setq day-wide-called t) - '()))) - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "All Day Event") - (intervals . ()))) - (events (list event))) - (chime--process-notifications events) - ;; Day-wide function should not be called - (should-not day-wide-called))))) - (test-chime-process-notifications-teardown))) + (let* ((now (test-time-today-at 14 0)) + (event-time (test-time-today-at 0 0)) + (timestamp-str (test-timestamp-string event-time t)) ; Day-wide + (day-wide-called nil)) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) (lambda (msg) nil)) + ;; Mock day-wide time to return false + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () nil)) + ((symbol-function 'chime--day-wide-notifications) + (lambda (events) + (setq day-wide-called t) + '()))) + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "All Day Event") + (intervals . ()))) + (events (list event))) + (chime--process-notifications events) + ;; Day-wide function should not be called + (should-not day-wide-called)))))) ;;; Boundary Cases -(ert-deftest test-chime-process-notifications-boundary-empty-events-no-notifications () +(chime-deftest test-chime-process-notifications-boundary-empty-events-no-notifications () "Test that empty events list produces no notifications. REFACTORED: No timestamps used" - (test-chime-process-notifications-setup) - (unwind-protect - (let ((notify-called nil)) - (cl-letf (((symbol-function 'chime--notify) - (lambda (msg) (setq notify-called t))) - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () nil))) - (let ((events '())) - (chime--process-notifications events) - ;; Should not call notify - (should-not notify-called)))) - (test-chime-process-notifications-teardown))) - -(ert-deftest test-chime-process-notifications-boundary-events-with-no-matches-no-notifications () + (let ((notify-called nil)) + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) (setq notify-called t))) + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () nil))) + (let ((events '())) + (chime--process-notifications events) + ;; Should not call notify + (should-not notify-called))))) + +(chime-deftest test-chime-process-notifications-boundary-events-with-no-matches-no-notifications () "Test that events with no matching notifications don't call notify. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-process-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Event at 15:00 (60 minutes away, doesn't match 10 min interval) - (event-time (test-time-today-at 15 0)) - (timestamp-str (test-timestamp-string event-time)) - (notify-called nil)) - (with-test-time now - (cl-letf (((symbol-function 'chime--notify) - (lambda (msg) (setq notify-called t))) - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () nil))) - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Future Event") - (intervals . ((10 . medium))))) - (events (list event))) - (chime--process-notifications events) - ;; Should not call notify - (should-not notify-called))))) - (test-chime-process-notifications-teardown))) - -(ert-deftest test-chime-process-notifications-boundary-single-event-edge-case () + (let* ((now (test-time-today-at 14 0)) + ;; Event at 15:00 (60 minutes away, doesn't match 10 min interval) + (event-time (test-time-today-at 15 0)) + (timestamp-str (test-timestamp-string event-time)) + (notify-called nil)) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) (setq notify-called t))) + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () nil))) + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Future Event") + (intervals . ((10 . medium))))) + (events (list event))) + (chime--process-notifications events) + ;; Should not call notify + (should-not notify-called)))))) + +(chime-deftest test-chime-process-notifications-boundary-single-event-edge-case () "Test processing single event works correctly. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-process-notifications-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)) - (notify-count 0)) - (with-test-time now - (cl-letf (((symbol-function 'chime--notify) - (lambda (msg) (setq notify-count (1+ notify-count)))) - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () nil))) - (let* ((event `((times . ((,timestamp-str . ,event-time))) - (title . "Single Event") - (intervals . ((10 . medium))))) - (events (list event))) - (chime--process-notifications events) - ;; Should call notify exactly once - (should (= 1 notify-count)))))) - (test-chime-process-notifications-teardown))) + (let* ((now (test-time-today-at 14 0)) + (event-time (test-time-today-at 14 10)) + (timestamp-str (test-timestamp-string event-time)) + (notify-count 0)) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) (setq notify-count (1+ notify-count)))) + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () nil))) + (let* ((event `((times . ((,timestamp-str . ,event-time))) + (title . "Single Event") + (intervals . ((10 . medium))))) + (events (list event))) + (chime--process-notifications events) + ;; Should call notify exactly once + (should (= 1 notify-count))))))) ;;; Error Cases -(ert-deftest test-chime-process-notifications-error-nil-events-handles-gracefully () +(chime-deftest test-chime-process-notifications-error-nil-events-handles-gracefully () "Test that nil events parameter doesn't crash. REFACTORED: No timestamps used" - (test-chime-process-notifications-setup) - (unwind-protect - (let ((notify-called nil)) - (cl-letf (((symbol-function 'chime--notify) - (lambda (msg) (setq notify-called t))) - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () nil))) - ;; Should not error with nil events - (should-not (condition-case nil - (progn (chime--process-notifications nil) nil) - (error t))) - ;; Should not call notify - (should-not notify-called))) - (test-chime-process-notifications-teardown))) - -(ert-deftest test-chime-process-notifications-error-invalid-event-structure-handles-gracefully () + (let ((notify-called nil)) + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) (setq notify-called t))) + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () nil))) + ;; Should not error with nil events + (should-not (condition-case nil + (progn (chime--process-notifications nil) nil) + (error t))) + ;; Should not call notify + (should-not notify-called)))) + +(chime-deftest test-chime-process-notifications-error-invalid-event-structure-handles-gracefully () "Test that invalid event structure doesn't crash. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-process-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - (notify-called nil)) - (with-test-time now - (cl-letf (((symbol-function 'chime--notify) - (lambda (msg) (setq notify-called t))) - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () nil))) - (let* (;; Invalid event: missing required fields - (events (list '((invalid . "structure"))))) - ;; Should not crash even with invalid events - (should-not (condition-case nil - (progn (chime--process-notifications events) nil) - (error t))))))) - (test-chime-process-notifications-teardown))) - -(ert-deftest test-chime-process-notifications-error-mixed-valid-invalid-events-processes-valid () + (let* ((now (test-time-today-at 14 0)) + (notify-called nil)) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) (setq notify-called t))) + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () nil))) + (let* (;; Invalid event: missing required fields + (events (list '((invalid . "structure"))))) + ;; Should not crash even with invalid events + (should-not (condition-case nil + (progn (chime--process-notifications events) nil) + (error t)))))))) + +(chime-deftest test-chime-process-notifications-error-mixed-valid-invalid-events-processes-valid () "Test that mix of valid and invalid events processes valid ones. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-process-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Valid event - (event-time (test-time-today-at 14 10)) - (timestamp-str (test-timestamp-string event-time)) - (notify-count 0)) - (with-test-time now - (cl-letf (((symbol-function 'chime--notify) - (lambda (msg) (setq notify-count (1+ notify-count)))) - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () nil))) - (let* ((valid-event `((times . ((,timestamp-str . ,event-time))) - (title . "Valid Event") - (intervals . ((10 . medium))))) - ;; Invalid event - (invalid-event '((invalid . "data"))) - (events (list valid-event invalid-event))) - ;; Should not crash - (should-not (condition-case nil - (progn (chime--process-notifications events) nil) - (error t))) - ;; Should process at least the valid event - (should (>= notify-count 1)))))) - (test-chime-process-notifications-teardown))) + (let* ((now (test-time-today-at 14 0)) + ;; Valid event + (event-time (test-time-today-at 14 10)) + (timestamp-str (test-timestamp-string event-time)) + (notify-count 0)) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) (setq notify-count (1+ notify-count)))) + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () nil))) + (let* ((valid-event `((times . ((,timestamp-str . ,event-time))) + (title . "Valid Event") + (intervals . ((10 . medium))))) + ;; Invalid event + (invalid-event '((invalid . "data"))) + (events (list valid-event invalid-event))) + ;; Should not crash + (should-not (condition-case nil + (progn (chime--process-notifications events) nil) + (error t))) + ;; Should process at least the valid event + (should (>= notify-count 1))))))) ;;; Day-wide bundling -(ert-deftest test-chime-process-notifications-day-wide-multiple-events-single-notify () +(chime-deftest test-chime-process-notifications-day-wide-multiple-events-single-notify () "Multiple day-wide events should produce a single bundled notification, not one notification per event." - (test-chime-process-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 8 0)) - (notify-count 0) - (notify-messages '())) - (with-test-time now - (cl-letf (((symbol-function 'chime--notify) - (lambda (msg) - (setq notify-count (1+ notify-count)) - (push msg notify-messages))) - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () t)) - ((symbol-function 'chime--day-wide-notifications) - (lambda (events) - (list (cons "Blake's birthday is today" 'medium) - (cons "Holiday: Memorial Day is today" 'medium) - (cons "Submit expense report is due or scheduled today" 'medium))))) - (chime--process-notifications '()) - ;; Should fire exactly ONE notification for all day-wide events - (should (= 1 notify-count)) - ;; The single notification body should contain all event messages - (let ((body (caar notify-messages))) - (should (string-match-p "Blake's birthday" body)) - (should (string-match-p "Memorial Day" body)) - (should (string-match-p "expense report" body)))))) - (test-chime-process-notifications-teardown))) - -(ert-deftest test-chime-process-notifications-day-wide-single-event-no-bundling () + (let* ((now (test-time-today-at 8 0)) + (notify-count 0) + (notify-messages '())) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) + (setq notify-count (1+ notify-count)) + (push msg notify-messages))) + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () t)) + ((symbol-function 'chime--day-wide-notifications) + (lambda (events) + (list (cons "Blake's birthday is today" 'medium) + (cons "Holiday: Memorial Day is today" 'medium) + (cons "Submit expense report is due or scheduled today" 'medium))))) + (chime--process-notifications '()) + ;; Should fire exactly ONE notification for all day-wide events + (should (= 1 notify-count)) + ;; The single notification body should contain all event messages + (let ((body (caar notify-messages))) + (should (string-match-p "Blake's birthday" body)) + (should (string-match-p "Memorial Day" body)) + (should (string-match-p "expense report" body))))))) + +(chime-deftest test-chime-process-notifications-day-wide-single-event-no-bundling () "A single day-wide event should produce a normal notification, not bundled." - (test-chime-process-notifications-setup) - (unwind-protect - (let* ((now (test-time-today-at 8 0)) - (notify-count 0) - (notify-messages '())) - (with-test-time now - (cl-letf (((symbol-function 'chime--notify) - (lambda (msg) - (setq notify-count (1+ notify-count)) - (push msg notify-messages))) - ((symbol-function 'chime--current-time-is-day-wide-time) - (lambda () t)) - ((symbol-function 'chime--day-wide-notifications) - (lambda (events) - (list (cons "Blake's birthday is today" 'medium))))) - (chime--process-notifications '()) - ;; Single event: still one notification - (should (= 1 notify-count)) - ;; Should be the plain message, not wrapped in a bundle - (let ((body (caar notify-messages))) - (should (string= "Blake's birthday is today" body)))))) - (test-chime-process-notifications-teardown))) + (let* ((now (test-time-today-at 8 0)) + (notify-count 0) + (notify-messages '())) + (with-test-time now + (cl-letf (((symbol-function 'chime--notify) + (lambda (msg) + (setq notify-count (1+ notify-count)) + (push msg notify-messages))) + ((symbol-function 'chime--current-time-is-day-wide-time) + (lambda () t)) + ((symbol-function 'chime--day-wide-notifications) + (lambda (events) + (list (cons "Blake's birthday is today" 'medium))))) + (chime--process-notifications '()) + ;; Single event: still one notification + (should (= 1 notify-count)) + ;; Should be the plain message, not wrapped in a bundle + (let ((body (caar notify-messages))) + (should (string= "Blake's birthday is today" body))))))) (provide 'test-chime-process-notifications) ;;; test-chime-process-notifications.el ends here diff --git a/tests/test-chime-propertize-modeline.el b/tests/test-chime-propertize-modeline.el index cc0dbb2..c0a0874 100644 --- a/tests/test-chime-propertize-modeline.el +++ b/tests/test-chime-propertize-modeline.el @@ -27,8 +27,6 @@ (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")) (require 'testutil-events (expand-file-name "testutil-events.el")) ;;; Setup/Teardown diff --git a/tests/test-chime-sanitize-title.el b/tests/test-chime-sanitize-title.el index 672cf70..8856a8e 100644 --- a/tests/test-chime-sanitize-title.el +++ b/tests/test-chime-sanitize-title.el @@ -32,358 +32,254 @@ (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-sanitize-title-setup () - "Setup function run before each test." - (chime-create-test-base-dir)) - -(defun test-chime-sanitize-title-teardown () - "Teardown function run after each test." - (chime-delete-test-base-dir)) - ;;; Normal Cases - Already Balanced -(ert-deftest test-chime-sanitize-title-balanced-parens-unchanged () +(chime-deftest test-chime-sanitize-title-balanced-parens-unchanged () "Test that balanced parentheses are unchanged. REFACTORED: No timestamps used" - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Meeting (Team Sync)") - (result (chime--sanitize-title title))) - (should (string-equal title result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-balanced-brackets-unchanged () + (let* ((title "Meeting (Team Sync)") + (result (chime--sanitize-title title))) + (should (string-equal title result)))) + +(chime-deftest test-chime-sanitize-title-balanced-brackets-unchanged () "Test that balanced brackets are unchanged. REFACTORED: No timestamps used" - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Review [PR #123]") - (result (chime--sanitize-title title))) - (should (string-equal title result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-balanced-braces-unchanged () + (let* ((title "Review [PR #123]") + (result (chime--sanitize-title title))) + (should (string-equal title result)))) + +(chime-deftest test-chime-sanitize-title-balanced-braces-unchanged () "Test that balanced braces are unchanged. REFACTORED: No timestamps used" - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Code Review {urgent}") - (result (chime--sanitize-title title))) - (should (string-equal title result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-mixed-balanced-unchanged () + (let* ((title "Code Review {urgent}") + (result (chime--sanitize-title title))) + (should (string-equal title result)))) + +(chime-deftest test-chime-sanitize-title-mixed-balanced-unchanged () "Test that mixed balanced delimiters are unchanged. REFACTORED: No timestamps used" - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Meeting [Team] (Sync) {Urgent}") - (result (chime--sanitize-title title))) - (should (string-equal title result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-nested-balanced-unchanged () + (let* ((title "Meeting [Team] (Sync) {Urgent}") + (result (chime--sanitize-title title))) + (should (string-equal title result)))) + +(chime-deftest test-chime-sanitize-title-nested-balanced-unchanged () "Test that nested balanced delimiters are unchanged. REFACTORED: No timestamps used" - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Review (PR [#123] {urgent})") - (result (chime--sanitize-title title))) - (should (string-equal title result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-no-delimiters-unchanged () + (let* ((title "Review (PR [#123] {urgent})") + (result (chime--sanitize-title title))) + (should (string-equal title result)))) + +(chime-deftest test-chime-sanitize-title-no-delimiters-unchanged () "Test that titles without delimiters are unchanged. REFACTORED: No timestamps used" - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Simple Meeting Title") - (result (chime--sanitize-title title))) - (should (string-equal title result))) - (test-chime-sanitize-title-teardown))) + (let* ((title "Simple Meeting Title") + (result (chime--sanitize-title title))) + (should (string-equal title result)))) ;;; Unmatched Opening Delimiters -(ert-deftest test-chime-sanitize-title-unmatched-opening-paren () +(chime-deftest test-chime-sanitize-title-unmatched-opening-paren () "Test that unmatched opening parenthesis is closed." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "CTO/COO XLT (Extended Leadership") - (result (chime--sanitize-title title))) - (should (string-equal "CTO/COO XLT (Extended Leadership)" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-unmatched-opening-paren-at-end () + (let* ((title "CTO/COO XLT (Extended Leadership") + (result (chime--sanitize-title title))) + (should (string-equal "CTO/COO XLT (Extended Leadership)" result)))) + +(chime-deftest test-chime-sanitize-title-unmatched-opening-paren-at-end () "Test that unmatched opening parenthesis at end is closed." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Spice Cake (") - (result (chime--sanitize-title title))) - (should (string-equal "Spice Cake ()" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-multiple-unmatched-opening-parens () + (let* ((title "Spice Cake (") + (result (chime--sanitize-title title))) + (should (string-equal "Spice Cake ()" result)))) + +(chime-deftest test-chime-sanitize-title-multiple-unmatched-opening-parens () "Test that multiple unmatched opening parentheses are closed." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Meeting (Team (Sync") - (result (chime--sanitize-title title))) - (should (string-equal "Meeting (Team (Sync))" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-unmatched-opening-bracket () + (let* ((title "Meeting (Team (Sync") + (result (chime--sanitize-title title))) + (should (string-equal "Meeting (Team (Sync))" result)))) + +(chime-deftest test-chime-sanitize-title-unmatched-opening-bracket () "Test that unmatched opening bracket is closed." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Review [PR #123") - (result (chime--sanitize-title title))) - (should (string-equal "Review [PR #123]" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-unmatched-opening-brace () + (let* ((title "Review [PR #123") + (result (chime--sanitize-title title))) + (should (string-equal "Review [PR #123]" result)))) + +(chime-deftest test-chime-sanitize-title-unmatched-opening-brace () "Test that unmatched opening brace is closed." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Code Review {urgent") - (result (chime--sanitize-title title))) - (should (string-equal "Code Review {urgent}" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-mixed-unmatched-opening-delimiters () + (let* ((title "Code Review {urgent") + (result (chime--sanitize-title title))) + (should (string-equal "Code Review {urgent}" result)))) + +(chime-deftest test-chime-sanitize-title-mixed-unmatched-opening-delimiters () "Test that mixed unmatched opening delimiters are all closed." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Meeting [Team (Sync {Urgent") - (result (chime--sanitize-title title))) - (should (string-equal "Meeting [Team (Sync {Urgent})]" result))) - (test-chime-sanitize-title-teardown))) + (let* ((title "Meeting [Team (Sync {Urgent") + (result (chime--sanitize-title title))) + (should (string-equal "Meeting [Team (Sync {Urgent})]" result)))) ;;; Unmatched Closing Delimiters -(ert-deftest test-chime-sanitize-title-unmatched-closing-paren () +(chime-deftest test-chime-sanitize-title-unmatched-closing-paren () "Test that unmatched closing parenthesis is removed." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Meeting Title)") - (result (chime--sanitize-title title))) - (should (string-equal "Meeting Title" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-multiple-unmatched-closing-parens () + (let* ((title "Meeting Title)") + (result (chime--sanitize-title title))) + (should (string-equal "Meeting Title" result)))) + +(chime-deftest test-chime-sanitize-title-multiple-unmatched-closing-parens () "Test that multiple unmatched closing parentheses are removed." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Meeting Title))") - (result (chime--sanitize-title title))) - (should (string-equal "Meeting Title" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-unmatched-closing-bracket () + (let* ((title "Meeting Title))") + (result (chime--sanitize-title title))) + (should (string-equal "Meeting Title" result)))) + +(chime-deftest test-chime-sanitize-title-unmatched-closing-bracket () "Test that unmatched closing bracket is removed." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Review PR]") - (result (chime--sanitize-title title))) - (should (string-equal "Review PR" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-unmatched-closing-brace () + (let* ((title "Review PR]") + (result (chime--sanitize-title title))) + (should (string-equal "Review PR" result)))) + +(chime-deftest test-chime-sanitize-title-unmatched-closing-brace () "Test that unmatched closing brace is removed." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Code Review}") - (result (chime--sanitize-title title))) - (should (string-equal "Code Review" result))) - (test-chime-sanitize-title-teardown))) + (let* ((title "Code Review}") + (result (chime--sanitize-title title))) + (should (string-equal "Code Review" result)))) ;;; Complex Mixed Cases -(ert-deftest test-chime-sanitize-title-opening-and-closing-mixed () +(chime-deftest test-chime-sanitize-title-opening-and-closing-mixed () "Test title with both unmatched opening and closing delimiters." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Meeting (Team) Extra)") - (result (chime--sanitize-title title))) - ;; Should remove the extra closing paren - (should (string-equal "Meeting (Team) Extra" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-complex-nesting-with-unmatched () + (let* ((title "Meeting (Team) Extra)") + (result (chime--sanitize-title title))) + ;; Should remove the extra closing paren + (should (string-equal "Meeting (Team) Extra" result)))) + +(chime-deftest test-chime-sanitize-title-complex-nesting-with-unmatched () "Test complex nested delimiters with some unmatched." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Meeting [Team (Sync] Extra") - (result (chime--sanitize-title title))) - ;; The ']' doesn't match the '[' (because '(' is in between) - ;; So it's removed, and we close the '(' and '[' properly: ')' and ']' - (should (string-equal "Meeting [Team (Sync Extra)]" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-all-types-unmatched () + (let* ((title "Meeting [Team (Sync] Extra") + (result (chime--sanitize-title title))) + ;; The ']' doesn't match the '[' (because '(' is in between) + ;; So it's removed, and we close the '(' and '[' properly: ')' and ']' + (should (string-equal "Meeting [Team (Sync Extra)]" result)))) + +(chime-deftest test-chime-sanitize-title-all-types-unmatched () "Test with all three delimiter types unmatched." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Meeting (Team [Project {Status") - (result (chime--sanitize-title title))) - (should (string-equal "Meeting (Team [Project {Status}])" result))) - (test-chime-sanitize-title-teardown))) + (let* ((title "Meeting (Team [Project {Status") + (result (chime--sanitize-title title))) + (should (string-equal "Meeting (Team [Project {Status}])" result)))) ;;; Edge Cases -(ert-deftest test-chime-sanitize-title-nil-returns-empty-string () +(chime-deftest test-chime-sanitize-title-nil-returns-empty-string () "Test that nil title returns empty string." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((result (chime--sanitize-title nil))) - (should (string-equal "" result))) - (test-chime-sanitize-title-teardown))) + (let* ((result (chime--sanitize-title nil))) + (should (string-equal "" result)))) -(ert-deftest test-chime-sanitize-title-empty-string-unchanged () +(chime-deftest test-chime-sanitize-title-empty-string-unchanged () "Test that empty string is unchanged." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "") - (result (chime--sanitize-title title))) - (should (string-equal "" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-only-opening-delimiters () + (let* ((title "") + (result (chime--sanitize-title title))) + (should (string-equal "" result)))) + +(chime-deftest test-chime-sanitize-title-only-opening-delimiters () "Test title with only opening delimiters." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "([{") - (result (chime--sanitize-title title))) - (should (string-equal "([{}])" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-only-closing-delimiters () + (let* ((title "([{") + (result (chime--sanitize-title title))) + (should (string-equal "([{}])" result)))) + +(chime-deftest test-chime-sanitize-title-only-closing-delimiters () "Test title with only closing delimiters." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title ")]}") - (result (chime--sanitize-title title))) - (should (string-equal "" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-very-long-title-with-unmatched () + (let* ((title ")]}") + (result (chime--sanitize-title title))) + (should (string-equal "" result)))) + +(chime-deftest test-chime-sanitize-title-very-long-title-with-unmatched () "Test very long title with unmatched delimiter." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "This is a very long meeting title that contains many words and might wrap in the notification display (Extended Info") - (result (chime--sanitize-title title))) - (should (string-equal "This is a very long meeting title that contains many words and might wrap in the notification display (Extended Info)" result))) - (test-chime-sanitize-title-teardown))) + (let* ((title "This is a very long meeting title that contains many words and might wrap in the notification display (Extended Info") + (result (chime--sanitize-title title))) + (should (string-equal "This is a very long meeting title that contains many words and might wrap in the notification display (Extended Info)" result)))) ;;; Real-World Bug Cases -(ert-deftest test-chime-sanitize-title-bug-case-extended-leadership () +(chime-deftest test-chime-sanitize-title-bug-case-extended-leadership () "Test the actual bug case from vineti.meetings.org." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "1:01pm CTO/COO XLT (Extended Leadership") - (result (chime--sanitize-title title))) - (should (string-equal "1:01pm CTO/COO XLT (Extended Leadership)" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-bug-case-spice-cake () + (let* ((title "1:01pm CTO/COO XLT (Extended Leadership") + (result (chime--sanitize-title title))) + (should (string-equal "1:01pm CTO/COO XLT (Extended Leadership)" result)))) + +(chime-deftest test-chime-sanitize-title-bug-case-spice-cake () "Test the actual bug case from journal/2023-11-22.org." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Spice Cake (") - (result (chime--sanitize-title title))) - (should (string-equal "Spice Cake ()" result))) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-sanitize-title-lisp-serialization-safety () - "Test that sanitized title can be safely read by Lisp reader." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((title "Meeting (Team Sync") - (sanitized (chime--sanitize-title title)) - ;; Simulate what happens in async serialization - (serialized (format "'((title . \"%s\"))" sanitized))) - ;; This should not signal an error - (should (listp (read serialized))) - (should (string-equal "Meeting (Team Sync)" sanitized))) - (test-chime-sanitize-title-teardown))) + (let* ((title "Spice Cake (") + (result (chime--sanitize-title title))) + (should (string-equal "Spice Cake ()" result)))) -(ert-deftest test-chime-sanitize-title-async-serialization-with-unmatched-parens () +(chime-deftest test-chime-sanitize-title-lisp-serialization-safety () + "Test that sanitized title can be safely read by Lisp reader." + (let* ((title "Meeting (Team Sync") + (sanitized (chime--sanitize-title title)) + ;; Simulate what happens in async serialization + (serialized (format "'((title . \"%s\"))" sanitized))) + ;; This should not signal an error + (should (listp (read serialized))) + (should (string-equal "Meeting (Team Sync)" sanitized)))) + +(chime-deftest test-chime-sanitize-title-async-serialization-with-unmatched-parens () "Test that titles with unmatched parens won't break async serialization." - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((problematic-titles '("Meeting (Team" - "Review [PR" - "Code {Status" - "Event ((" - "Task ))"))) - (dolist (title problematic-titles) - (let* ((sanitized (chime--sanitize-title title)) - (serialized (format "'((title . \"%s\"))" sanitized))) - ;; Should not signal 'invalid-read-syntax error - (should (listp (read serialized)))))) - (test-chime-sanitize-title-teardown))) + (let* ((problematic-titles '("Meeting (Team" + "Review [PR" + "Code {Status" + "Event ((" + "Task ))"))) + (dolist (title problematic-titles) + (let* ((sanitized (chime--sanitize-title title)) + (serialized (format "'((title . \"%s\"))" sanitized))) + ;; Should not signal 'invalid-read-syntax error + (should (listp (read serialized))))))) ;;; Integration with chime--extract-title -(ert-deftest test-chime-extract-title-sanitizes-output () +(chime-deftest test-chime-extract-title-sanitizes-output () "Test that chime--extract-title applies sanitization. REFACTORED: Uses dynamic timestamps" - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 0)) - (timestamp (test-timestamp-string time)) - (test-file (chime-create-temp-test-file-with-content - (format "* TODO Meeting (Team Sync\n%s\n" timestamp))) - (test-buffer (find-file-noselect test-file))) - (with-current-buffer test-buffer - (org-mode) ; Enable org-mode - (goto-char (point-min)) - ;; Search for the heading - (re-search-forward "^\\* TODO" nil t) - (beginning-of-line) - (let* ((marker (point-marker)) - (title (chime--extract-title marker))) - ;; Should be sanitized with closing paren added - (should (string-equal "Meeting (Team Sync)" title)))) - (kill-buffer test-buffer)) - (test-chime-sanitize-title-teardown))) - -(ert-deftest test-chime-extract-title-handles-nil () + (let* ((time (test-time-tomorrow-at 14 0)) + (timestamp (test-timestamp-string time)) + (test-file (chime-create-temp-test-file-with-content + (format "* TODO Meeting (Team Sync\n%s\n" timestamp))) + (test-buffer (find-file-noselect test-file))) + (with-current-buffer test-buffer + (org-mode) ; Enable org-mode + (goto-char (point-min)) + ;; Search for the heading + (re-search-forward "^\\* TODO" nil t) + (beginning-of-line) + (let* ((marker (point-marker)) + (title (chime--extract-title marker))) + ;; Should be sanitized with closing paren added + (should (string-equal "Meeting (Team Sync)" title)))) + (kill-buffer test-buffer))) + +(chime-deftest test-chime-extract-title-handles-nil () "Test that chime--extract-title handles nil gracefully. REFACTORED: Uses dynamic timestamps" - (test-chime-sanitize-title-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 0)) - (timestamp (test-timestamp-string time)) - (test-file (chime-create-temp-test-file-with-content - (format "* TODO\n%s\n" timestamp))) - (test-buffer (find-file-noselect test-file))) - (with-current-buffer test-buffer - (org-mode) ; Enable org-mode - (goto-char (point-min)) - ;; Search for the heading - (re-search-forward "^\\* TODO" nil t) - (beginning-of-line) - (let* ((marker (point-marker)) - (title (chime--extract-title marker))) - ;; Should return empty string for nil title - (should (string-equal "" title)))) - (kill-buffer test-buffer)) - (test-chime-sanitize-title-teardown))) + (let* ((time (test-time-tomorrow-at 14 0)) + (timestamp (test-timestamp-string time)) + (test-file (chime-create-temp-test-file-with-content + (format "* TODO\n%s\n" timestamp))) + (test-buffer (find-file-noselect test-file))) + (with-current-buffer test-buffer + (org-mode) ; Enable org-mode + (goto-char (point-min)) + ;; Search for the heading + (re-search-forward "^\\* TODO" nil t) + (beginning-of-line) + (let* ((marker (point-marker)) + (title (chime--extract-title marker))) + ;; Should return empty string for nil title + (should (string-equal "" title)))) + (kill-buffer test-buffer))) (provide 'test-chime-sanitize-title) ;;; test-chime-sanitize-title.el ends here diff --git a/tests/test-chime-time-left.el b/tests/test-chime-time-left.el index b9bd176..5d27636 100644 --- a/tests/test-chime-time-left.el +++ b/tests/test-chime-time-left.el @@ -26,9 +26,6 @@ (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -;; Load test utilities -(require 'testutil-general (expand-file-name "testutil-general.el")) - ;;; Setup and Teardown (defun test-chime-time-left-setup () diff --git a/tests/test-chime-time-utilities.el b/tests/test-chime-time-utilities.el index 26e4d96..29488df 100644 --- a/tests/test-chime-time-utilities.el +++ b/tests/test-chime-time-utilities.el @@ -28,10 +28,6 @@ (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")) - ;;;; Tests for chime--get-minutes-into-day ;;; Normal Cases diff --git a/tests/test-chime-timestamp-parse.el b/tests/test-chime-timestamp-parse.el index 5dc30bf..e06b832 100644 --- a/tests/test-chime-timestamp-parse.el +++ b/tests/test-chime-timestamp-parse.el @@ -26,375 +26,283 @@ (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-timestamp-parse-setup () - "Setup function run before each test." - (chime-create-test-base-dir)) - -(defun test-chime-timestamp-parse-teardown () - "Teardown function run after each test." - (chime-delete-test-base-dir)) - ;;; Normal Cases -(ert-deftest test-chime-timestamp-parse-standard-timestamp-returns-time-list () +(chime-deftest test-chime-timestamp-parse-standard-timestamp-returns-time-list () "Test that a standard timestamp with time component returns a time list. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 30)) - (timestamp (test-timestamp-string time)) - (result (chime--timestamp-parse timestamp))) - ;; Should return a time list (list of integers) - (should (listp result)) - (should (= (length result) 2)) - (should (integerp (car result))) - (should (integerp (cadr result))) - ;; Result should not be nil - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-scheduled-timestamp-returns-time-list () + (let* ((time (test-time-tomorrow-at 14 30)) + (timestamp (test-timestamp-string time)) + (result (chime--timestamp-parse timestamp))) + ;; Should return a time list (list of integers) + (should (listp result)) + (should (= (length result) 2)) + (should (integerp (car result))) + (should (integerp (cadr result))) + ;; Result should not be nil + (should result))) + +(chime-deftest test-chime-timestamp-parse-scheduled-timestamp-returns-time-list () "Test that a SCHEDULED timestamp parses correctly. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 9 0)) - (timestamp (test-timestamp-string time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-deadline-timestamp-returns-time-list () + (let* ((time (test-time-tomorrow-at 9 0)) + (timestamp (test-timestamp-string time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) + +(chime-deftest test-chime-timestamp-parse-deadline-timestamp-returns-time-list () "Test that a DEADLINE timestamp parses correctly. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 17 0)) - (timestamp (test-timestamp-string time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-timestamp-with-weekly-repeater-returns-time-list () + (let* ((time (test-time-tomorrow-at 17 0)) + (timestamp (test-timestamp-string time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) + +(chime-deftest test-chime-timestamp-parse-timestamp-with-weekly-repeater-returns-time-list () "Test that a timestamp with +1w repeater parses correctly. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 0)) - (timestamp (format-time-string "<%Y-%m-%d %a %H:%M +1w>" time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-timestamp-with-completion-repeater-returns-time-list () + (let* ((time (test-time-tomorrow-at 14 0)) + (timestamp (format-time-string "<%Y-%m-%d %a %H:%M +1w>" time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) + +(chime-deftest test-chime-timestamp-parse-timestamp-with-completion-repeater-returns-time-list () "Test that a timestamp with .+1d repeater parses correctly. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 8 0)) - (timestamp (format-time-string "<%Y-%m-%d %a %H:%M .+1d>" time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-timestamp-with-catchup-repeater-returns-time-list () + (let* ((time (test-time-tomorrow-at 8 0)) + (timestamp (format-time-string "<%Y-%m-%d %a %H:%M .+1d>" time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) + +(chime-deftest test-chime-timestamp-parse-timestamp-with-catchup-repeater-returns-time-list () "Test that a timestamp with ++1w repeater parses correctly. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 10 30)) - (timestamp (format-time-string "<%Y-%m-%d %a %H:%M ++1w>" time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-timestamp-with-time-range-returns-start-time () + (let* ((time (test-time-tomorrow-at 10 30)) + (timestamp (format-time-string "<%Y-%m-%d %a %H:%M ++1w>" time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) + +(chime-deftest test-chime-timestamp-parse-timestamp-with-time-range-returns-start-time () "Test that a timestamp with time range returns the start time. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 14 0)) - (timestamp (format-time-string "<%Y-%m-%d %a %H:%M-15:30>" time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-timestamp-with-date-range-returns-start-date () + (let* ((time (test-time-tomorrow-at 14 0)) + (timestamp (format-time-string "<%Y-%m-%d %a %H:%M-15:30>" time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) + +(chime-deftest test-chime-timestamp-parse-timestamp-with-date-range-returns-start-date () "Test that a timestamp with date range returns start date time. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((time1 (test-time-tomorrow-at 10 0)) - (time2 (test-time-days-from-now 2)) - (timestamp (concat (test-timestamp-string time1) "--" - (format-time-string "<%Y-%m-%d %a %H:%M>" time2))) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) + (let* ((time1 (test-time-tomorrow-at 10 0)) + (time2 (test-time-days-from-now 2)) + (timestamp (concat (test-timestamp-string time1) "--" + (format-time-string "<%Y-%m-%d %a %H:%M>" time2))) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) ;;; Boundary Cases -(ert-deftest test-chime-timestamp-parse-midnight-timestamp-returns-time-list () +(chime-deftest test-chime-timestamp-parse-midnight-timestamp-returns-time-list () "Test that midnight (00:00) timestamp parses correctly. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 0 0)) - (timestamp (test-timestamp-string time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-last-minute-of-day-returns-time-list () + (let* ((time (test-time-tomorrow-at 0 0)) + (timestamp (test-timestamp-string time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) + +(chime-deftest test-chime-timestamp-parse-last-minute-of-day-returns-time-list () "Test that last minute of day (23:59) timestamp parses correctly. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 23 59)) - (timestamp (test-timestamp-string time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-year-boundary-new-years-eve-returns-time-list () + (let* ((time (test-time-tomorrow-at 23 59)) + (timestamp (test-timestamp-string time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) + +(chime-deftest test-chime-timestamp-parse-year-boundary-new-years-eve-returns-time-list () "Test that New Year's Eve timestamp parses correctly. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((now (test-time-now)) - (decoded (decode-time now)) - (year (nth 5 decoded)) - ;; Create Dec 31 at 23:30 for current test year - (time (encode-time 0 30 23 31 12 year)) - (timestamp (test-timestamp-string time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-year-boundary-new-years-day-returns-time-list () + (let* ((now (test-time-now)) + (decoded (decode-time now)) + (year (nth 5 decoded)) + ;; Create Dec 31 at 23:30 for current test year + (time (encode-time 0 30 23 31 12 year)) + (timestamp (test-timestamp-string time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) + +(chime-deftest test-chime-timestamp-parse-year-boundary-new-years-day-returns-time-list () "Test that New Year's Day timestamp parses correctly. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((now (test-time-now)) - (decoded (decode-time now)) - (year (1+ (nth 5 decoded))) ; Next year - ;; Create Jan 1 at 00:30 for next test year - (time (encode-time 0 30 0 1 1 year)) - (timestamp (test-timestamp-string time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-single-digit-time-returns-time-list () + (let* ((now (test-time-now)) + (decoded (decode-time now)) + (year (1+ (nth 5 decoded))) ; Next year + ;; Create Jan 1 at 00:30 for next test year + (time (encode-time 0 30 0 1 1 year)) + (timestamp (test-timestamp-string time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) + +(chime-deftest test-chime-timestamp-parse-single-digit-time-returns-time-list () "Test that single-digit hours and minutes parse correctly. REFACTORED: Uses dynamic timestamps" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((time (test-time-tomorrow-at 1 5)) - (timestamp (test-timestamp-string time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-leap-year-feb-29-returns-time-list () + (let* ((time (test-time-tomorrow-at 1 5)) + (timestamp (test-timestamp-string time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) + +(chime-deftest test-chime-timestamp-parse-leap-year-feb-29-returns-time-list () "Test that Feb 29 in leap year parses correctly. REFACTORED: Uses dynamic timestamps (2024 leap year)" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* (;; Use 2024 as a known leap year - (time (encode-time 0 0 14 29 2 2024)) - (timestamp (test-timestamp-string time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-month-boundary-end-of-month-returns-time-list () + (let* (;; Use 2024 as a known leap year + (time (encode-time 0 0 14 29 2 2024)) + (timestamp (test-timestamp-string time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) + +(chime-deftest test-chime-timestamp-parse-month-boundary-end-of-month-returns-time-list () "Test that end of month timestamp parses correctly. REFACTORED: Uses dynamic timestamps (Oct 31)" - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((now (test-time-now)) - (decoded (decode-time now)) - (year (nth 5 decoded)) - ;; Create Oct 31 at 14:00 for current test year - (time (encode-time 0 0 14 31 10 year)) - (timestamp (test-timestamp-string time)) - (result (chime--timestamp-parse timestamp))) - (should (listp result)) - (should (= (length result) 2)) - (should result)) - (test-chime-timestamp-parse-teardown))) + (let* ((now (test-time-now)) + (decoded (decode-time now)) + (year (nth 5 decoded)) + ;; Create Oct 31 at 14:00 for current test year + (time (encode-time 0 0 14 31 10 year)) + (timestamp (test-timestamp-string time)) + (result (chime--timestamp-parse timestamp))) + (should (listp result)) + (should (= (length result) 2)) + (should result))) ;;; Bug Reproduction Tests -(ert-deftest test-chime-timestamp-parse-tomorrow-timestamp-returns-correct-date () +(chime-deftest test-chime-timestamp-parse-tomorrow-timestamp-returns-correct-date () "Test that a tomorrow timestamp is parsed as tomorrow, not today. This reproduces the bug where timestamps like <2025-11-03 Mon 10:00-10:30> on Nov 02 are incorrectly grouped as 'Today' instead of 'Tomorrow'." - (test-chime-timestamp-parse-setup) - (unwind-protect - (with-test-time (encode-time 0 23 11 2 11 2025) ; Nov 02, 2025 11:23:00 AM - (let* ((tomorrow-timestamp "<2025-11-03 Mon 10:00-10:30>") - (parsed (chime--timestamp-parse tomorrow-timestamp)) - (now (current-time))) - ;; Should parse successfully - (should parsed) - ;; Convert parsed time (HIGH LOW) to full time by appending (0 0) - (let* ((parsed-time (append parsed '(0 0))) - (parsed-decoded (decode-time parsed-time)) - (time-diff-seconds (- (time-to-seconds parsed-time) - (time-to-seconds now)))) - ;; Verify the parsed date is Nov 03, 2025 (not Nov 02!) - (should (= 3 (decoded-time-day parsed-decoded))) - (should (= 11 (decoded-time-month parsed-decoded))) - (should (= 2025 (decoded-time-year parsed-decoded))) - ;; Verify the parsed time is 10:00 - (should (= 10 (decoded-time-hour parsed-decoded))) - (should (= 0 (decoded-time-minute parsed-decoded))) - ;; Time difference should be ~22h 37m (81420 seconds) - (should (> time-diff-seconds 81360)) ; At least 22h 36m - (should (< time-diff-seconds 81480))))) ; At most 22h 38m - (test-chime-timestamp-parse-teardown))) + (with-test-time (encode-time 0 23 11 2 11 2025) ; Nov 02, 2025 11:23:00 AM + (let* ((tomorrow-timestamp "<2025-11-03 Mon 10:00-10:30>") + (parsed (chime--timestamp-parse tomorrow-timestamp)) + (now (current-time))) + ;; Should parse successfully + (should parsed) + ;; Convert parsed time (HIGH LOW) to full time by appending (0 0) + (let* ((parsed-time (append parsed '(0 0))) + (parsed-decoded (decode-time parsed-time)) + (time-diff-seconds (- (time-to-seconds parsed-time) + (time-to-seconds now)))) + ;; Verify the parsed date is Nov 03, 2025 (not Nov 02!) + (should (= 3 (decoded-time-day parsed-decoded))) + (should (= 11 (decoded-time-month parsed-decoded))) + (should (= 2025 (decoded-time-year parsed-decoded))) + ;; Verify the parsed time is 10:00 + (should (= 10 (decoded-time-hour parsed-decoded))) + (should (= 0 (decoded-time-minute parsed-decoded))) + ;; Time difference should be ~22h 37m (81420 seconds) + (should (> time-diff-seconds 81360)) ; At least 22h 36m + (should (< time-diff-seconds 81480)))))) ;;; Error Cases -(ert-deftest test-chime-timestamp-parse-empty-string-returns-nil () +(chime-deftest test-chime-timestamp-parse-empty-string-returns-nil () "Test that empty string returns nil." - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((timestamp "") - (result (chime--timestamp-parse timestamp))) - (should (null result))) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-nil-input-returns-nil () + (let* ((timestamp "") + (result (chime--timestamp-parse timestamp))) + (should (null result)))) + +(chime-deftest test-chime-timestamp-parse-nil-input-returns-nil () "Test that nil input returns nil." - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((timestamp nil) - (result (chime--timestamp-parse timestamp))) - (should (null result))) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-missing-opening-bracket-returns-nil () + (let* ((timestamp nil) + (result (chime--timestamp-parse timestamp))) + (should (null result)))) + +(chime-deftest test-chime-timestamp-parse-missing-opening-bracket-returns-nil () "Test that timestamp missing opening bracket returns nil." - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((timestamp "2025-10-24 Fri 14:00>") - (result (chime--timestamp-parse timestamp))) - (should (null result))) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-missing-closing-bracket-returns-nil () + (let* ((timestamp "2025-10-24 Fri 14:00>") + (result (chime--timestamp-parse timestamp))) + (should (null result)))) + +(chime-deftest test-chime-timestamp-parse-missing-closing-bracket-returns-nil () "Test that timestamp missing closing bracket returns nil." - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((timestamp "<2025-10-24 Fri 14:00") - (result (chime--timestamp-parse timestamp))) - (should (null result))) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-invalid-date-format-returns-nil () + (let* ((timestamp "<2025-10-24 Fri 14:00") + (result (chime--timestamp-parse timestamp))) + (should (null result)))) + +(chime-deftest test-chime-timestamp-parse-invalid-date-format-returns-nil () "Test that invalid date format returns nil." - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((timestamp "<10-24-2025 Fri 14:00>") - (result (chime--timestamp-parse timestamp))) - (should (null result))) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-invalid-month-returns-nil () + (let* ((timestamp "<10-24-2025 Fri 14:00>") + (result (chime--timestamp-parse timestamp))) + (should (null result)))) + +(chime-deftest test-chime-timestamp-parse-invalid-month-returns-nil () "Test that invalid month value returns nil." - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((timestamp "<2025-13-24 Fri 14:00>") - (result (chime--timestamp-parse timestamp))) - (should (null result))) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-invalid-day-returns-nil () + (let* ((timestamp "<2025-13-24 Fri 14:00>") + (result (chime--timestamp-parse timestamp))) + (should (null result)))) + +(chime-deftest test-chime-timestamp-parse-invalid-day-returns-nil () "Test that invalid day value returns nil." - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((timestamp "<2025-10-32 Fri 14:00>") - (result (chime--timestamp-parse timestamp))) - (should (null result))) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-invalid-time-hour-returns-nil () + (let* ((timestamp "<2025-10-32 Fri 14:00>") + (result (chime--timestamp-parse timestamp))) + (should (null result)))) + +(chime-deftest test-chime-timestamp-parse-invalid-time-hour-returns-nil () "Test that invalid hour value returns nil." - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((timestamp "<2025-10-24 Fri 25:00>") - (result (chime--timestamp-parse timestamp))) - (should (null result))) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-invalid-time-minute-returns-nil () + (let* ((timestamp "<2025-10-24 Fri 25:00>") + (result (chime--timestamp-parse timestamp))) + (should (null result)))) + +(chime-deftest test-chime-timestamp-parse-invalid-time-minute-returns-nil () "Test that invalid minute value returns nil." - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((timestamp "<2025-10-24 Fri 14:60>") - (result (chime--timestamp-parse timestamp))) - (should (null result))) - (test-chime-timestamp-parse-teardown))) - -(ert-deftest test-chime-timestamp-parse-date-only-no-time-returns-nil () + (let* ((timestamp "<2025-10-24 Fri 14:60>") + (result (chime--timestamp-parse timestamp))) + (should (null result)))) + +(chime-deftest test-chime-timestamp-parse-date-only-no-time-returns-nil () "Test that day-wide timestamp without time returns nil." - (test-chime-timestamp-parse-setup) - (unwind-protect - (let* ((timestamp "<2025-10-24 Fri>") - (result (chime--timestamp-parse timestamp))) - (should (null result))) - (test-chime-timestamp-parse-teardown))) + (let* ((timestamp "<2025-10-24 Fri>") + (result (chime--timestamp-parse timestamp))) + (should (null result)))) (provide 'test-chime-timestamp-parse) ;;; test-chime-timestamp-parse.el ends here diff --git a/tests/test-chime-timestamp-within-interval-p.el b/tests/test-chime-timestamp-within-interval-p.el index 2cb6439..5857463 100644 --- a/tests/test-chime-timestamp-within-interval-p.el +++ b/tests/test-chime-timestamp-within-interval-p.el @@ -26,287 +26,222 @@ (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-timestamp-within-interval-p-setup () - "Setup function run before each test." - (chime-create-test-base-dir)) - -(defun test-chime-timestamp-within-interval-p-teardown () - "Teardown function run after each test." - (chime-delete-test-base-dir)) - ;;; Normal Cases -(ert-deftest test-chime-timestamp-within-interval-p-exactly-at-interval-returns-t () +(chime-deftest test-chime-timestamp-within-interval-p-exactly-at-interval-returns-t () "Test that timestamp exactly at interval returns t. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Timestamp at 14:10 (10 minutes from 14:00) - (timestamp (test-time-today-at 14 10)) - (interval 10)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-zero-interval-returns-t () + (let* ((now (test-time-today-at 14 0)) + ;; Timestamp at 14:10 (10 minutes from 14:00) + (timestamp (test-time-today-at 14 10)) + (interval 10)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-zero-interval-returns-t () "Test that zero interval (notify now) returns t for current time. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 30)) - ;; Timestamp at exactly current time (14:30) - (timestamp (test-time-today-at 14 30)) - (interval 0)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-five-minutes-returns-t () + (let* ((now (test-time-today-at 14 30)) + ;; Timestamp at exactly current time (14:30) + (timestamp (test-time-today-at 14 30)) + (interval 0)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-five-minutes-returns-t () "Test that 5-minute interval works correctly. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 25)) - ;; Timestamp at 14:30 (5 minutes from 14:25) - (timestamp (test-time-today-at 14 30)) - (interval 5)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-sixty-minutes-returns-t () + (let* ((now (test-time-today-at 14 25)) + ;; Timestamp at 14:30 (5 minutes from 14:25) + (timestamp (test-time-today-at 14 30)) + (interval 5)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-sixty-minutes-returns-t () "Test that 60-minute (1 hour) interval works correctly. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Timestamp at 15:00 (60 minutes from 14:00) - (timestamp (test-time-today-at 15 0)) - (interval 60)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-large-interval-returns-t () + (let* ((now (test-time-today-at 14 0)) + ;; Timestamp at 15:00 (60 minutes from 14:00) + (timestamp (test-time-today-at 15 0)) + (interval 60)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-large-interval-returns-t () "Test that large interval (1 day = 1440 minutes) works correctly. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Timestamp at 14:00 next day (1440 minutes from now) - ;; Add 86400 seconds (1440 minutes = 1 day) to now - ;; Convert to list format for compatibility - (timestamp (apply #'encode-time (decode-time (time-add now (seconds-to-time 86400))))) - (interval 1440)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-thirty-minutes-returns-t () + (let* ((now (test-time-today-at 14 0)) + ;; Timestamp at 14:00 next day (1440 minutes from now) + ;; Add 86400 seconds (1440 minutes = 1 day) to now + ;; Convert to list format for compatibility + (timestamp (apply #'encode-time (decode-time (time-add now (seconds-to-time 86400))))) + (interval 1440)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-thirty-minutes-returns-t () "Test that 30-minute interval works correctly. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 15)) - ;; Timestamp at 14:45 (30 minutes from 14:15) - (timestamp (test-time-today-at 14 45)) - (interval 30)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should result)))) - (test-chime-timestamp-within-interval-p-teardown))) + (let* ((now (test-time-today-at 14 15)) + ;; Timestamp at 14:45 (30 minutes from 14:15) + (timestamp (test-time-today-at 14 45)) + (interval 30)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should result))))) ;;; Boundary Cases -(ert-deftest test-chime-timestamp-within-interval-p-one-minute-before-returns-nil () +(chime-deftest test-chime-timestamp-within-interval-p-one-minute-before-returns-nil () "Test that timestamp 1 minute before interval returns nil. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Timestamp at 14:09 (9 minutes from 14:00, not 10) - (timestamp (test-time-today-at 14 9)) - (interval 10)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should-not result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-one-minute-after-returns-nil () + (let* ((now (test-time-today-at 14 0)) + ;; Timestamp at 14:09 (9 minutes from 14:00, not 10) + (timestamp (test-time-today-at 14 9)) + (interval 10)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should-not result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-one-minute-after-returns-nil () "Test that timestamp 1 minute after interval returns nil. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Timestamp at 14:11 (11 minutes from 14:00, not 10) - (timestamp (test-time-today-at 14 11)) - (interval 10)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should-not result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-crossing-midnight-returns-t () + (let* ((now (test-time-today-at 14 0)) + ;; Timestamp at 14:11 (11 minutes from 14:00, not 10) + (timestamp (test-time-today-at 14 11)) + (interval 10)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should-not result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-crossing-midnight-returns-t () "Test that interval crossing midnight works correctly. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 23 50)) - ;; Timestamp at 00:00 next day (10 minutes from 23:50) - ;; Add 600 seconds (10 minutes) to 23:50 to get 00:00 next day - ;; Convert to list format for compatibility - (timestamp (apply #'encode-time (decode-time (time-add now (seconds-to-time 600))))) - (interval 10)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-crossing-day-boundary-returns-t () + (let* ((now (test-time-today-at 23 50)) + ;; Timestamp at 00:00 next day (10 minutes from 23:50) + ;; Add 600 seconds (10 minutes) to 23:50 to get 00:00 next day + ;; Convert to list format for compatibility + (timestamp (apply #'encode-time (decode-time (time-add now (seconds-to-time 600))))) + (interval 10)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-crossing-day-boundary-returns-t () "Test that interval crossing to next day works correctly. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 23 30)) - ;; Timestamp at 00:30 next day (60 minutes from 23:30) - ;; Add 3600 seconds (60 minutes) to 23:30 to get 00:30 next day - ;; Convert to list format for compatibility - (timestamp (apply #'encode-time (decode-time (time-add now (seconds-to-time 3600))))) - (interval 60)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-week-interval-returns-t () + (let* ((now (test-time-today-at 23 30)) + ;; Timestamp at 00:30 next day (60 minutes from 23:30) + ;; Add 3600 seconds (60 minutes) to 23:30 to get 00:30 next day + ;; Convert to list format for compatibility + (timestamp (apply #'encode-time (decode-time (time-add now (seconds-to-time 3600))))) + (interval 60)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-week-interval-returns-t () "Test that very large interval (1 week = 10080 minutes) works. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Timestamp at 14:00 one week later (10080 minutes = 7 days from now) - ;; Add 604800 seconds (10080 minutes = 7 days) to now - ;; Convert to list format for compatibility - (timestamp (apply #'encode-time (decode-time (time-add now (seconds-to-time 604800))))) - (interval 10080)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-at-midnight-returns-t () + (let* ((now (test-time-today-at 14 0)) + ;; Timestamp at 14:00 one week later (10080 minutes = 7 days from now) + ;; Add 604800 seconds (10080 minutes = 7 days) to now + ;; Convert to list format for compatibility + (timestamp (apply #'encode-time (decode-time (time-add now (seconds-to-time 604800))))) + (interval 10080)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-at-midnight-returns-t () "Test that timestamp at exact midnight works correctly. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 23 50)) - ;; Timestamp at midnight (10 minutes from 23:50) - ;; Add 600 seconds (10 minutes) to 23:50 to get 00:00 next day - ;; Convert to list format for compatibility - (timestamp (apply #'encode-time (decode-time (time-add now (seconds-to-time 600))))) - (interval 10)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should result)))) - (test-chime-timestamp-within-interval-p-teardown))) + (let* ((now (test-time-today-at 23 50)) + ;; Timestamp at midnight (10 minutes from 23:50) + ;; Add 600 seconds (10 minutes) to 23:50 to get 00:00 next day + ;; Convert to list format for compatibility + (timestamp (apply #'encode-time (decode-time (time-add now (seconds-to-time 600))))) + (interval 10)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should result))))) ;;; Error Cases -(ert-deftest test-chime-timestamp-within-interval-p-nil-timestamp-returns-nil () +(chime-deftest test-chime-timestamp-within-interval-p-nil-timestamp-returns-nil () "Test that nil timestamp returns nil. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - (timestamp nil) - (interval 10)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should-not result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-nil-interval-returns-nil () + (let* ((now (test-time-today-at 14 0)) + (timestamp nil) + (interval 10)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should-not result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-nil-interval-returns-nil () "Test that nil interval returns nil. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - (timestamp (test-time-today-at 14 10)) - (interval nil)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should-not result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-negative-interval-returns-nil () + (let* ((now (test-time-today-at 14 0)) + (timestamp (test-time-today-at 14 10)) + (interval nil)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should-not result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-negative-interval-returns-nil () "Test that negative interval returns nil (past timestamps). REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Timestamp 10 minutes in the past (13:50) - (timestamp (test-time-today-at 13 50)) - (interval -10)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-invalid-timestamp-returns-nil () + (let* ((now (test-time-today-at 14 0)) + ;; Timestamp 10 minutes in the past (13:50) + (timestamp (test-time-today-at 13 50)) + (interval -10)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-invalid-timestamp-returns-nil () "Test that invalid timestamp format returns nil. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - (timestamp "not-a-timestamp") - (interval 10)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should-not result)))) - (test-chime-timestamp-within-interval-p-teardown))) - -(ert-deftest test-chime-timestamp-within-interval-p-float-interval-works () + (let* ((now (test-time-today-at 14 0)) + (timestamp "not-a-timestamp") + (interval 10)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should-not result))))) + +(chime-deftest test-chime-timestamp-within-interval-p-float-interval-works () "Test that float interval gets converted properly. REFACTORED: Uses dynamic timestamps and with-test-time" - (test-chime-timestamp-within-interval-p-setup) - (unwind-protect - (let* ((now (test-time-today-at 14 0)) - ;; Timestamp at 14:10 (10 minutes from 14:00) - (timestamp (test-time-today-at 14 10)) - (interval 10.5)) - (with-test-time now - (let ((result (chime--timestamp-within-interval-p timestamp interval))) - (should result)))) - (test-chime-timestamp-within-interval-p-teardown))) + (let* ((now (test-time-today-at 14 0)) + ;; Timestamp at 14:10 (10 minutes from 14:00) + (timestamp (test-time-today-at 14 10)) + (interval 10.5)) + (with-test-time now + (let ((result (chime--timestamp-within-interval-p timestamp interval))) + (should result))))) (provide 'test-chime-timestamp-within-interval-p) ;;; test-chime-timestamp-within-interval-p.el ends here diff --git a/tests/test-chime-tooltip-bugs.el b/tests/test-chime-tooltip-bugs.el index 8a11317..0d141b9 100644 --- a/tests/test-chime-tooltip-bugs.el +++ b/tests/test-chime-tooltip-bugs.el @@ -8,8 +8,6 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-general (expand-file-name "testutil-general.el")) -(require 'testutil-time (expand-file-name "testutil-time.el")) ;;; Setup and Teardown diff --git a/tests/test-chime-tooltip-day-calculation.el b/tests/test-chime-tooltip-day-calculation.el index 6e4f778..724ff9d 100644 --- a/tests/test-chime-tooltip-day-calculation.el +++ b/tests/test-chime-tooltip-day-calculation.el @@ -13,8 +13,6 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-time (expand-file-name "testutil-time.el")) -(require 'testutil-general (expand-file-name "testutil-general.el")) (require 'testutil-events (expand-file-name "testutil-events.el")) (defmacro test-chime-tooltip-day-calculation--with-tooltip (now content &rest body) diff --git a/tests/test-chime-update-modeline-helpers.el b/tests/test-chime-update-modeline-helpers.el index 429265c..f28ad81 100644 --- a/tests/test-chime-update-modeline-helpers.el +++ b/tests/test-chime-update-modeline-helpers.el @@ -10,8 +10,6 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-time (expand-file-name "testutil-time.el")) -(require 'testutil-general (expand-file-name "testutil-general.el")) (require 'testutil-events (expand-file-name "testutil-events.el")) ;;;; Tests for chime--find-soonest-time-in-window diff --git a/tests/test-chime-update-modeline.el b/tests/test-chime-update-modeline.el index 525e39e..7b1a809 100644 --- a/tests/test-chime-update-modeline.el +++ b/tests/test-chime-update-modeline.el @@ -26,10 +26,6 @@ (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-update-modeline-setup () diff --git a/tests/test-chime-validation-retry.el b/tests/test-chime-validation-retry.el index a2765f4..ec5e2fe 100644 --- a/tests/test-chime-validation-retry.el +++ b/tests/test-chime-validation-retry.el @@ -20,8 +20,6 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-general (expand-file-name "testutil-general.el")) -(require 'testutil-time (expand-file-name "testutil-time.el")) (require 'testutil-events (expand-file-name "testutil-events.el")) ;;; Setup and Teardown diff --git a/tests/test-chime-whitelist-blacklist-conflicts.el b/tests/test-chime-whitelist-blacklist-conflicts.el index 18b6680..b2465c5 100644 --- a/tests/test-chime-whitelist-blacklist-conflicts.el +++ b/tests/test-chime-whitelist-blacklist-conflicts.el @@ -30,9 +30,6 @@ (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -;; Load test utilities -(require 'testutil-general (expand-file-name "testutil-general.el")) - ;;; Setup and Teardown (defun test-chime-conflicts-setup () diff --git a/tests/test-integration-chime-mode.el b/tests/test-integration-chime-mode.el index 40436fb..229d877 100644 --- a/tests/test-integration-chime-mode.el +++ b/tests/test-integration-chime-mode.el @@ -28,8 +28,6 @@ (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")) (require 'testutil-events (expand-file-name "testutil-events.el")) ;;; Tests diff --git a/tests/test-integration-per-event-override.el b/tests/test-integration-per-event-override.el index 8455590..119e345 100644 --- a/tests/test-integration-per-event-override.el +++ b/tests/test-integration-per-event-override.el @@ -32,7 +32,6 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-general (expand-file-name "testutil-general.el")) (require 'cl-lib) (defun test-integration-per-event-override--events-from-agenda () diff --git a/tests/test-integration-recurring-events-tooltip.el b/tests/test-integration-recurring-events-tooltip.el index 810e3ee..c904d37 100644 --- a/tests/test-integration-recurring-events-tooltip.el +++ b/tests/test-integration-recurring-events-tooltip.el @@ -42,10 +42,6 @@ (setq chime-debug t) (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 (defvar test-integration-recurring--orig-agenda-files nil diff --git a/tests/test-integration-startup.el b/tests/test-integration-startup.el index 1f60b54..952a975 100644 --- a/tests/test-integration-startup.el +++ b/tests/test-integration-startup.el @@ -45,8 +45,6 @@ (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")) (require 'testutil-events (expand-file-name "testutil-events.el")) ;;; Helper Functions diff --git a/tests/test-testutil-general.el b/tests/test-testutil-general.el index 7b4e445..c3c89f2 100644 --- a/tests/test-testutil-general.el +++ b/tests/test-testutil-general.el @@ -9,7 +9,6 @@ ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) -(require 'testutil-general (expand-file-name "testutil-general.el")) (ert-deftest test-chime-test-default-base-dir-uses-env-override () "Normal: CHIME_TEST_TMPDIR selects an explicit test root." |
