aboutsummaryrefslogtreecommitdiff
path: root/tests/test-config-utilities--validate-timestamps-in-buffer.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-04-30 09:25:18 -0500
committerCraig Jennings <c@cjennings.net>2026-04-30 09:25:18 -0500
commit467a6d63f44ba835a94e7580adff9ff6b2b1a1eb (patch)
tree1399981f7689280884229a96acce6225dbd2aefd /tests/test-config-utilities--validate-timestamps-in-buffer.el
parentf90a087d5025952f0ca1b81d322f29891a40e540 (diff)
downloaddotemacs-467a6d63f44ba835a94e7580adff9ff6b2b1a1eb.tar.gz
dotemacs-467a6d63f44ba835a94e7580adff9ff6b2b1a1eb.zip
test(config-utilities): cover validate-timestamps and format-report helpers
Two test files covering the extracted timestamp-validation helpers. cj/--validate-timestamps-in-buffer (8 tests): empty buffer no-op, buffer with no timestamps, buffer with all valid timestamps, DEADLINE flagged with "DEADLINE" property, SCHEDULED flagged with "SCHEDULED", inline-timestamp flagged with "inline timestamp", multiple invalid collected in document order, mixed valid+invalid returning only the invalid one. Tests use real org parsing and mock org-time-string-to-absolute at the boundary so an arbitrary timestamp can be marked invalid for a given test. cj/--format-validation-report-section (4 tests): no-entries says "No invalid timestamps found", single-entry produces the file: link + Property/Type + Invalid timestamp lines, multiple-entry preserves input order, every section ends with a trailing blank line.
Diffstat (limited to 'tests/test-config-utilities--validate-timestamps-in-buffer.el')
-rw-r--r--tests/test-config-utilities--validate-timestamps-in-buffer.el130
1 files changed, 130 insertions, 0 deletions
diff --git a/tests/test-config-utilities--validate-timestamps-in-buffer.el b/tests/test-config-utilities--validate-timestamps-in-buffer.el
new file mode 100644
index 00000000..8ca51a55
--- /dev/null
+++ b/tests/test-config-utilities--validate-timestamps-in-buffer.el
@@ -0,0 +1,130 @@
+;;; test-config-utilities--validate-timestamps-in-buffer.el --- Tests for cj/--validate-timestamps-in-buffer -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Tests for `cj/--validate-timestamps-in-buffer'. The function walks
+;; an org buffer's headlines, checks DEADLINE/SCHEDULED/TIMESTAMP
+;; properties plus inline timestamps, and returns a list of tuples
+;; for every timestamp where `org-time-string-to-absolute' returns
+;; nil. Tests use real org parsing on real timestamps and mock the
+;; validator at the boundary so an arbitrary timestamp can be marked
+;; invalid for the test.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'config-utilities)
+(require 'org)
+(require 'org-element)
+
+(defmacro test-config-utilities--with-org-buffer (content &rest body)
+ "Run BODY in a temp buffer holding CONTENT in `org-mode'."
+ (declare (indent 1) (debug t))
+ `(with-temp-buffer
+ (let ((org-mode-hook nil))
+ (insert ,content)
+ (org-mode)
+ ,@body)))
+
+(defmacro test-config-utilities--with-invalid-timestamps (invalid-set &rest body)
+ "Run BODY with `org-time-string-to-absolute' returning nil for any
+timestamp string in INVALID-SET, normal behaviour otherwise."
+ (declare (indent 1) (debug t))
+ `(let ((--invalid-set ,invalid-set)
+ (--orig (symbol-function 'org-time-string-to-absolute)))
+ (cl-letf (((symbol-function 'org-time-string-to-absolute)
+ (lambda (s &rest args)
+ (if (member s --invalid-set)
+ (error "test-mocked invalid timestamp: %s" s)
+ (apply --orig s args)))))
+ ,@body)))
+
+(ert-deftest test-config-utilities-validate-buffer-no-timestamps-returns-empty ()
+ "Boundary: a buffer with no timestamps returns an empty list."
+ (test-config-utilities--with-org-buffer "* Heading\nJust prose.\n"
+ (should-not (cj/--validate-timestamps-in-buffer "/x.org"))))
+
+(ert-deftest test-config-utilities-validate-buffer-empty-buffer-returns-empty ()
+ "Boundary: an empty buffer returns an empty list."
+ (test-config-utilities--with-org-buffer ""
+ (should-not (cj/--validate-timestamps-in-buffer "/x.org"))))
+
+(ert-deftest test-config-utilities-validate-buffer-valid-timestamps-returns-empty ()
+ "Normal: every valid timestamp passes; the result is empty."
+ (test-config-utilities--with-org-buffer
+ "* Headline
+DEADLINE: <2026-04-30 Thu>
+"
+ (should-not (cj/--validate-timestamps-in-buffer "/x.org"))))
+
+(ert-deftest test-config-utilities-validate-buffer-deadline-flagged-when-invalid ()
+ "Normal: an invalid DEADLINE is flagged with property \"DEADLINE\"."
+ (test-config-utilities--with-org-buffer
+ "* Bad
+DEADLINE: <2026-04-30 Thu>
+"
+ (test-config-utilities--with-invalid-timestamps '("<2026-04-30 Thu>")
+ (let ((result (cj/--validate-timestamps-in-buffer "/x.org")))
+ (should (= 1 (length result)))
+ (cl-destructuring-bind (file _pos head prop ts) (car result)
+ (should (equal file "/x.org"))
+ (should (equal head "Bad"))
+ (should (equal prop "DEADLINE"))
+ (should (equal ts "<2026-04-30 Thu>")))))))
+
+(ert-deftest test-config-utilities-validate-buffer-scheduled-flagged-when-invalid ()
+ "Normal: an invalid SCHEDULED is flagged with property \"SCHEDULED\"."
+ (test-config-utilities--with-org-buffer
+ "* Sched
+SCHEDULED: <2026-05-01 Fri>
+"
+ (test-config-utilities--with-invalid-timestamps '("<2026-05-01 Fri>")
+ (let ((result (cj/--validate-timestamps-in-buffer "/x.org")))
+ (should (= 1 (length result)))
+ (should (equal "SCHEDULED" (nth 3 (car result))))))))
+
+(ert-deftest test-config-utilities-validate-buffer-inline-flagged-as-inline ()
+ "Normal: an invalid inline timestamp in headline contents is flagged
+with property \"inline timestamp\"."
+ (test-config-utilities--with-org-buffer
+ "* Body has timestamp
+Some prose mentioning <2026-06-01 Mon> in passing.
+"
+ (test-config-utilities--with-invalid-timestamps '("<2026-06-01 Mon>")
+ (let ((result (cj/--validate-timestamps-in-buffer "/x.org")))
+ (should (= 1 (length result)))
+ (should (equal "inline timestamp" (nth 3 (car result))))))))
+
+(ert-deftest test-config-utilities-validate-buffer-multiple-invalid-collected-in-order ()
+ "Normal: multiple invalid timestamps are returned in document order."
+ (test-config-utilities--with-org-buffer
+ "* First
+DEADLINE: <2026-01-01 Thu>
+* Second
+SCHEDULED: <2026-02-02 Mon>
+"
+ (test-config-utilities--with-invalid-timestamps
+ '("<2026-01-01 Thu>" "<2026-02-02 Mon>")
+ (let ((result (cj/--validate-timestamps-in-buffer "/x.org")))
+ (should (= 2 (length result)))
+ (should (equal "First" (nth 2 (nth 0 result))))
+ (should (equal "Second" (nth 2 (nth 1 result))))))))
+
+(ert-deftest test-config-utilities-validate-buffer-mixed-valid-and-invalid ()
+ "Boundary: buffer with one valid and one invalid timestamp returns
+only the invalid one."
+ (test-config-utilities--with-org-buffer
+ "* Good
+DEADLINE: <2026-04-30 Thu>
+* Bad
+DEADLINE: <2026-12-25 Fri>
+"
+ (test-config-utilities--with-invalid-timestamps '("<2026-12-25 Fri>")
+ (let ((result (cj/--validate-timestamps-in-buffer "/x.org")))
+ (should (= 1 (length result)))
+ (should (equal "Bad" (nth 2 (car result))))))))
+
+(provide 'test-config-utilities--validate-timestamps-in-buffer)
+;;; test-config-utilities--validate-timestamps-in-buffer.el ends here