aboutsummaryrefslogtreecommitdiff
path: root/tests/test-org-drill-time-to-inactive-org-timestamp.el
blob: 8676ece8440ba1567772db4357233132f9891977 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
;;; test-org-drill-time-to-inactive-org-timestamp.el --- Tests for inactive org-timestamp formatting  -*- lexical-binding: t; -*-

;;; Commentary:
;; Regression tests for `org-drill-time-to-inactive-org-timestamp'.
;;
;; Upstream issue #59 (chipschap, 2025-08-28) reported broken timestamps
;; like `[Y-08-27 Wed 16:%]' written into DRILL_LAST_REVIEWED.  Root
;; cause: in Org 9.6+, `(cdr org-time-stamp-formats)' returns the format
;; string without the angle brackets it had pre-9.6.  The original
;; `(substring ... 1 -1)' assumed brackets and stripped the leading `%'
;; of `%Y' and the trailing `M' of `%M', producing `Y-%m-%d %a %H:%' as
;; the format directive.  format-time-string then interpolated `Y' as a
;; literal and left a trailing `%]' in the output.
;;
;; Cherry-pick 4c6e62a switched the Org 9.6+ path to
;; `(org-time-stamp-format t 'no-bracket)' (which despite the arg name
;; *does* return a bracketed format).  These tests lock that behavior
;; in.

;;; Code:

(require 'ert)
(require 'org-drill)

(defconst test-tts-fixed-time
  ;; Saturday 2024-06-15 12:30:00 local time.
  (encode-time 0 30 12 15 6 2024)
  "Fixed reference time used by these tests.")

(defconst test-tts-timestamp-regex
  "\\`\\[[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [A-Z][a-z][a-z] [0-9]\\{2\\}:[0-9]\\{2\\}\\]\\'"
  "Anchored regex for a well-formed inactive org-timestamp like `[2024-06-15 Sat 12:30]'.")

;;;; Normal cases

(ert-deftest test-org-drill-time-to-inactive-org-timestamp-normal-fixed-time-matches-shape ()
  "A normal time produces a bracketed YYYY-MM-DD Day HH:MM string."
  (let ((result (org-drill-time-to-inactive-org-timestamp test-tts-fixed-time)))
    (should (string-match-p test-tts-timestamp-regex result))))

(ert-deftest test-org-drill-time-to-inactive-org-timestamp-normal-fixed-time-exact-string ()
  "The fixed reference time produces the expected literal timestamp."
  (should (equal (org-drill-time-to-inactive-org-timestamp test-tts-fixed-time)
                 "[2024-06-15 Sat 12:30]")))

;;;; Boundary cases

(ert-deftest test-org-drill-time-to-inactive-org-timestamp-boundary-midnight ()
  "Midnight (00:00) formats correctly with leading zeros."
  (let* ((midnight (encode-time 0 0 0 1 1 2024))
         (result (org-drill-time-to-inactive-org-timestamp midnight)))
    (should (string-match-p test-tts-timestamp-regex result))
    (should (string-match-p "00:00\\]\\'" result))))

(ert-deftest test-org-drill-time-to-inactive-org-timestamp-boundary-end-of-year ()
  "Last minute of the year formats correctly."
  (let* ((eoy (encode-time 0 59 23 31 12 2024))
         (result (org-drill-time-to-inactive-org-timestamp eoy)))
    (should (string-match-p test-tts-timestamp-regex result))
    (should (string-match-p "2024-12-31" result))
    (should (string-match-p "23:59\\]\\'" result))))

(ert-deftest test-org-drill-time-to-inactive-org-timestamp-boundary-leap-day ()
  "Feb 29 on a leap year formats correctly."
  (let* ((leap (encode-time 0 0 12 29 2 2024))
         (result (org-drill-time-to-inactive-org-timestamp leap)))
    (should (string-match-p test-tts-timestamp-regex result))
    (should (string-match-p "2024-02-29" result))))

;;;; Error / regression cases

(ert-deftest test-org-drill-time-to-inactive-org-timestamp-error-no-stray-percent-directives ()
  "Issue #59 regression: output must not contain stray `%' characters.

Pre-fix, Org 9.6+ produced timestamps like `[Y-08-27 Wed 16:%]' because the
Org 9.5-shaped substring slicing dropped the leading `%' of `%Y' and the
trailing `M' of `%M'.  Any literal `%' in the output indicates the format
string lost a directive."
  (let ((result (org-drill-time-to-inactive-org-timestamp test-tts-fixed-time)))
    (should-not (string-match-p "%" result))))

(ert-deftest test-org-drill-time-to-inactive-org-timestamp-error-year-not-literal-Y ()
  "Issue #59 regression: the year must be four digits, not the literal char `Y'."
  (let ((result (org-drill-time-to-inactive-org-timestamp test-tts-fixed-time)))
    (should-not (string-match-p "\\[Y-" result))
    (should (string-match-p "\\[2024-" result))))

(provide 'test-org-drill-time-to-inactive-org-timestamp)

;;; test-org-drill-time-to-inactive-org-timestamp.el ends here