aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-11 05:02:17 -0500
committerCraig Jennings <c@cjennings.net>2026-05-11 05:02:17 -0500
commit73faba8658ea783bca8392e4d4cc14cf7f94a48f (patch)
tree4a7fd70eaae4ca5244d9bccdfbc2e25e6386be11
parent5dcf7a3123f924ff9ad29ad8591679a0bf0a2565 (diff)
downloadchime-73faba8658ea783bca8392e4d4cc14cf7f94a48f.tar.gz
chime-73faba8658ea783bca8392e4d4cc14cf7f94a48f.zip
test: add failing tests for per-event interval override
I added fifteen tests ahead of the implementation, covering the per-event :CHIME_NOTIFY_BEFORE: property and the deprecated :WILD_NOTIFIER_NOTIFY_BEFORE: alias: value-string parsing (chime--parse-notify-before-value), property lookup with global fallback (chime--intervals-for-marker), the gather path (chime--gather-info honoring the property and flagging the alias on the event), and the once-per-session deprecation warning (chime--maybe-warn-deprecated-properties). They all fail with void-function for the not-yet-defined helpers, plus a length mismatch on the gather-info tests since chime--gather-info still uses the global chime-alert-intervals.
-rw-r--r--tests/test-chime-intervals-for-marker.el208
1 files changed, 208 insertions, 0 deletions
diff --git a/tests/test-chime-intervals-for-marker.el b/tests/test-chime-intervals-for-marker.el
new file mode 100644
index 0000000..1d74077
--- /dev/null
+++ b/tests/test-chime-intervals-for-marker.el
@@ -0,0 +1,208 @@
+;;; test-chime-intervals-for-marker.el --- Tests for per-event interval override -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2026 Craig Jennings
+
+;; Author: Craig Jennings <c@cjennings.net>
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for the per-event :CHIME_NOTIFY_BEFORE: property override and the
+;; deprecated :WILD_NOTIFIER_NOTIFY_BEFORE: alias:
+;;
+;; - chime--parse-notify-before-value : value-string parsing
+;; - chime--intervals-for-marker : property lookup with fallback to
+;; chime-alert-intervals; returns
+;; (INTERVALS . DEPRECATED-PROP)
+;; - chime--gather-info : end-to-end gather honoring the property
+;; - chime--maybe-warn-deprecated-properties : one-warning-per-session guard
+
+;;; Code:
+
+(require 'test-bootstrap (expand-file-name "test-bootstrap.el"))
+(require 'cl-lib)
+
+;;; Helpers
+
+(defun test-chime-intervals--org-heading-with-props (props)
+ "Return org content for one heading whose drawer carries PROPS.
+PROPS is a list of (NAME . VALUE) string pairs, or nil for no drawer."
+ (concat "* Test Heading\n"
+ (when props
+ (concat ":PROPERTIES:\n"
+ (mapconcat (lambda (p) (format ":%s: %s\n" (car p) (cdr p)))
+ props "")
+ ":END:\n"))
+ "<2026-05-12 Tue 14:00>\n"))
+
+(defmacro test-chime-intervals--with-marker (props &rest body)
+ "Run BODY in a temp org buffer with a heading carrying PROPS; bind `marker'."
+ (declare (indent 1) (debug t))
+ `(with-temp-buffer
+ (org-mode)
+ (insert (test-chime-intervals--org-heading-with-props ,props))
+ (goto-char (point-min))
+ (let ((marker (point-marker)))
+ ,@body)))
+
+(defmacro test-chime-intervals--capture-messages (var &rest body)
+ "Run BODY with `message' calls captured into VAR (chronological)."
+ (declare (indent 1) (debug t))
+ `(let ((,var nil))
+ (cl-letf (((symbol-function 'message)
+ (lambda (fmt &rest args)
+ (push (apply #'format fmt args) ,var))))
+ ,@body)
+ (setq ,var (nreverse ,var))))
+
+;;; chime--parse-notify-before-value
+
+(ert-deftest test-chime-parse-notify-before-value-normal-and-boundary ()
+ "Normal/Boundary: non-negative integer strings parse to integers."
+ (dolist (case '(("30" . 30) ("0" . 0) (" 30 " . 30) ("007" . 7) ("1440" . 1440)))
+ (should (= (cdr case)
+ (chime--parse-notify-before-value (car case))))))
+
+(ert-deftest test-chime-parse-notify-before-value-error-cases ()
+ "Error: non-integer, negative, fractional, empty, suffixed, and nil values yield nil."
+ (dolist (bad '("abc" "-5" "30.5" "" " " "30m" nil))
+ (should-not (chime--parse-notify-before-value bad))))
+
+;;; chime--intervals-for-marker
+
+(ert-deftest test-chime-intervals-for-marker-normal-no-property-uses-global ()
+ "Normal: with no override property, returns (chime-alert-intervals . nil)."
+ (let ((chime-alert-intervals '((10 . medium) (0 . high))))
+ (test-chime-intervals--with-marker nil
+ (should (equal (cons '((10 . medium) (0 . high)) nil)
+ (chime--intervals-for-marker marker))))))
+
+(ert-deftest test-chime-intervals-for-marker-normal-canonical-property ()
+ "Normal: :CHIME_NOTIFY_BEFORE: 30 yields (((30 . medium)) . nil)."
+ (test-chime-intervals--with-marker '(("CHIME_NOTIFY_BEFORE" . "30"))
+ (should (equal (cons '((30 . medium)) nil)
+ (chime--intervals-for-marker marker)))))
+
+(ert-deftest test-chime-intervals-for-marker-normal-deprecated-alias ()
+ "Normal: :WILD_NOTIFIER_NOTIFY_BEFORE: 15 yields the override and flags the alias."
+ (test-chime-intervals--with-marker '(("WILD_NOTIFIER_NOTIFY_BEFORE" . "15"))
+ (should (equal (cons '((15 . medium)) "WILD_NOTIFIER_NOTIFY_BEFORE")
+ (chime--intervals-for-marker marker)))))
+
+(ert-deftest test-chime-intervals-for-marker-normal-canonical-wins-over-alias ()
+ "Normal: with both properties set, the canonical one wins and the alias is not flagged."
+ (test-chime-intervals--with-marker '(("CHIME_NOTIFY_BEFORE" . "5")
+ ("WILD_NOTIFIER_NOTIFY_BEFORE" . "60"))
+ (should (equal (cons '((5 . medium)) nil)
+ (chime--intervals-for-marker marker)))))
+
+(ert-deftest test-chime-intervals-for-marker-boundary-zero ()
+ "Boundary: :CHIME_NOTIFY_BEFORE: 0 means notify at event time."
+ (test-chime-intervals--with-marker '(("CHIME_NOTIFY_BEFORE" . "0"))
+ (should (equal (cons '((0 . medium)) nil)
+ (chime--intervals-for-marker marker)))))
+
+(ert-deftest test-chime-intervals-for-marker-error-malformed-canonical-falls-back ()
+ "Error: a malformed :CHIME_NOTIFY_BEFORE: value logs and falls back to the global."
+ (let ((chime-alert-intervals '((10 . medium))))
+ (test-chime-intervals--with-marker '(("CHIME_NOTIFY_BEFORE" . "soon"))
+ (test-chime-intervals--capture-messages messages
+ (should (equal (cons '((10 . medium)) nil)
+ (chime--intervals-for-marker marker))))
+ (should (cl-some (lambda (m) (string-match-p "CHIME_NOTIFY_BEFORE" m)) messages)))))
+
+(ert-deftest test-chime-intervals-for-marker-error-malformed-alias-falls-back ()
+ "Error: a malformed deprecated-alias value logs and falls back to the global."
+ (let ((chime-alert-intervals '((10 . medium))))
+ (test-chime-intervals--with-marker '(("WILD_NOTIFIER_NOTIFY_BEFORE" . "-3"))
+ (test-chime-intervals--capture-messages messages
+ (should (equal (cons '((10 . medium)) nil)
+ (chime--intervals-for-marker marker))))
+ (should (cl-some (lambda (m) (string-match-p "WILD_NOTIFIER_NOTIFY_BEFORE" m)) messages)))))
+
+;;; chime--gather-info integration
+
+(ert-deftest test-chime-gather-info-integration-applies-canonical-override ()
+ "Integration: a heading with :CHIME_NOTIFY_BEFORE: 25 gathers an event with ((25 . medium))."
+ (with-temp-buffer
+ (org-mode)
+ (insert "* Meeting\n:PROPERTIES:\n:CHIME_NOTIFY_BEFORE: 25\n:END:\n<2026-05-12 Tue 14:00>\n")
+ (goto-char (point-min))
+ (let ((event (chime--gather-info (point-marker))))
+ (should (equal '((25 . medium)) (chime--event-intervals event)))
+ (should-not (chime--event-deprecated-property event)))))
+
+(ert-deftest test-chime-gather-info-integration-flags-deprecated-alias ()
+ "Integration: a heading with the deprecated alias gathers an event carrying the deprecation flag."
+ (with-temp-buffer
+ (org-mode)
+ (insert "* Meeting\n:PROPERTIES:\n:WILD_NOTIFIER_NOTIFY_BEFORE: 20\n:END:\n<2026-05-12 Tue 14:00>\n")
+ (goto-char (point-min))
+ (let ((event (chime--gather-info (point-marker))))
+ (should (equal '((20 . medium)) (chime--event-intervals event)))
+ (should (string= "WILD_NOTIFIER_NOTIFY_BEFORE"
+ (chime--event-deprecated-property event))))))
+
+(ert-deftest test-chime-gather-info-integration-no-override-uses-global ()
+ "Integration: a heading without the property gathers with chime-alert-intervals."
+ (let ((chime-alert-intervals '((10 . medium) (0 . high))))
+ (with-temp-buffer
+ (org-mode)
+ (insert "* Meeting\n<2026-05-12 Tue 14:00>\n")
+ (goto-char (point-min))
+ (let ((event (chime--gather-info (point-marker))))
+ (should (equal '((10 . medium) (0 . high)) (chime--event-intervals event)))
+ (should-not (chime--event-deprecated-property event))))))
+
+;;; chime--maybe-warn-deprecated-properties
+
+(ert-deftest test-chime-maybe-warn-deprecated-properties-normal-warns-once ()
+ "Normal: the first events list carrying a deprecated property triggers one warning."
+ (let ((chime--deprecated-property-warned nil)
+ (warned nil))
+ (cl-letf (((symbol-function 'display-warning)
+ (lambda (_type msg &rest _) (push msg warned))))
+ (chime--maybe-warn-deprecated-properties
+ (list (chime--make-event '(("<2026-05-12 Tue 14:00>" . (1 2))) "A" '((10 . medium)))
+ (chime--make-event '(("<2026-05-12 Tue 15:00>" . (3 4))) "B" '((20 . medium))
+ nil nil "WILD_NOTIFIER_NOTIFY_BEFORE")))
+ (should (= 1 (length warned)))
+ (should chime--deprecated-property-warned)
+ (should (string-match-p "WILD_NOTIFIER_NOTIFY_BEFORE" (car warned))))))
+
+(ert-deftest test-chime-maybe-warn-deprecated-properties-boundary-no-deprecated-no-warning ()
+ "Boundary: events with no deprecated property produce no warning, guard stays nil."
+ (let ((chime--deprecated-property-warned nil)
+ (warned nil))
+ (cl-letf (((symbol-function 'display-warning)
+ (lambda (&rest _) (push t warned))))
+ (chime--maybe-warn-deprecated-properties
+ (list (chime--make-event '(("<2026-05-12 Tue 14:00>" . (1 2))) "A" '((10 . medium)))))
+ (should (null warned))
+ (should-not chime--deprecated-property-warned))))
+
+(ert-deftest test-chime-maybe-warn-deprecated-properties-boundary-already-warned-no-repeat ()
+ "Boundary: once the session guard is set, no further warning fires."
+ (let ((chime--deprecated-property-warned t)
+ (warned nil))
+ (cl-letf (((symbol-function 'display-warning)
+ (lambda (&rest _) (push t warned))))
+ (chime--maybe-warn-deprecated-properties
+ (list (chime--make-event '(("<2026-05-12 Tue 14:00>" . (1 2))) "A" '((20 . medium))
+ nil nil "WILD_NOTIFIER_NOTIFY_BEFORE")))
+ (should (null warned)))))
+
+(provide 'test-chime-intervals-for-marker)
+;;; test-chime-intervals-for-marker.el ends here