aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-05 04:29:32 -0500
committerCraig Jennings <c@cjennings.net>2026-05-05 04:29:32 -0500
commit08fbd97864ef86ed127e0d6a5fb3005c53db47f8 (patch)
treeaffe7ca6e0867828bfa3256faee5349306b56267
parentb2cc4d1645b378043a971906b5ebc34d3c92b544 (diff)
downloadorg-drill-08fbd97864ef86ed127e0d6a5fb3005c53db47f8.tar.gz
org-drill-08fbd97864ef86ed127e0d6a5fb3005c53db47f8.zip
test: add coverage for org-drill-smart-reschedule
6 ERT tests covering all four days-ahead branches: - 0 → unschedule (treat as new again) - negative → schedule today (current-time) - positive → schedule N days ahead - nil → use the algorithm-computed next-interval (locks in the numberp guard fix) Plus property side-effects: writes DRILL_LAST_INTERVAL / EASE / TOTAL_REPEATS via store-item-data, and TOTAL_REPEATS increments on each call.
-rw-r--r--tests/test-org-drill-smart-reschedule.el119
1 files changed, 119 insertions, 0 deletions
diff --git a/tests/test-org-drill-smart-reschedule.el b/tests/test-org-drill-smart-reschedule.el
new file mode 100644
index 0000000..49eddb0
--- /dev/null
+++ b/tests/test-org-drill-smart-reschedule.el
@@ -0,0 +1,119 @@
+;;; test-org-drill-smart-reschedule.el --- Tests for smart-reschedule -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Tests for `org-drill-smart-reschedule', the function that runs after a
+;; user rates a card. It updates the card's DRILL_* properties via
+;; store-item-data and then sets a fresh SCHEDULED stamp.
+;;
+;; Three days-ahead branches:
+;;
+;; - 0 → unschedule (treat as new again)
+;; - <0 → schedule for today (right now)
+;; - >0 → schedule N days from today
+;; - nil → use the algorithm-computed next-interval (this branch was
+;; broken before the fix — `(= 0 nil)' errored).
+;;
+;; The user-facing contract: rate a card, see the next-review date
+;; advance to a sensible point.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+(require 'org)
+(require 'org-drill)
+
+;;;; Helpers
+
+(defmacro with-fresh-drill-entry (&rest body)
+ (declare (indent 0))
+ `(with-temp-buffer
+ (let ((org-startup-folded nil))
+ (insert "* Question :drill:\n")
+ (org-mode)
+ (goto-char (point-min))
+ ,@body)))
+
+(defmacro with-fixed-now (&rest body)
+ `(cl-letf (((symbol-function 'current-time)
+ (lambda () (encode-time 0 0 12 5 5 2026))))
+ ,@body))
+
+(defun current-scheduled-time-string ()
+ "Return SCHEDULED stamp on entry at point or nil."
+ (org-entry-get (point) "SCHEDULED"))
+
+;;;; Branch: days-ahead = 0 (unschedule)
+
+(ert-deftest test-org-drill-smart-reschedule-zero-days-ahead-unschedules ()
+ "Passing 0 removes the SCHEDULED stamp — the entry is treated as new again."
+ (with-fresh-drill-entry
+ (org-schedule nil "2026-05-01")
+ (with-fixed-now
+ (org-drill-smart-reschedule 4 0))
+ (should (null (current-scheduled-time-string)))))
+
+;;;; Branch: days-ahead < 0 (today)
+
+(ert-deftest test-org-drill-smart-reschedule-negative-schedules-today ()
+ "Negative days-ahead schedules for current-time (today)."
+ (with-fresh-drill-entry
+ (with-fixed-now
+ (org-drill-smart-reschedule 4 -1))
+ (let ((scheduled (current-scheduled-time-string)))
+ (should scheduled)
+ ;; Scheduled stamp matches today's date.
+ (should (string-match-p "2026-05-05" scheduled)))))
+
+;;;; Branch: days-ahead > 0 (N days from today)
+
+(ert-deftest test-org-drill-smart-reschedule-positive-schedules-n-days-ahead ()
+ "Positive days-ahead schedules exactly N days into the future."
+ (with-fresh-drill-entry
+ (with-fixed-now
+ (org-drill-smart-reschedule 4 7))
+ (let ((scheduled (current-scheduled-time-string)))
+ (should scheduled)
+ ;; 2026-05-05 + 7 days = 2026-05-12.
+ (should (string-match-p "2026-05-12" scheduled)))))
+
+;;;; Branch: days-ahead = nil (use algorithm)
+
+(ert-deftest test-org-drill-smart-reschedule-nil-days-ahead-uses-algorithm ()
+ "Without days-ahead, fall back to the scheduler's computed next-interval.
+Pre-fix this branch crashed with `Wrong type argument: number-or-marker-p, nil'
+because the cond compared nil with `=' before the type-guard."
+ (with-fresh-drill-entry
+ (with-fixed-now
+ ;; Should not error. The scheduled date should be in the future
+ ;; (some sensible interval).
+ (org-drill-smart-reschedule 5)
+ (let ((scheduled (current-scheduled-time-string)))
+ (should scheduled)))))
+
+;;;; Property side-effects
+
+(ert-deftest test-org-drill-smart-reschedule-writes-drill-properties ()
+ "Rescheduling also writes DRILL_* properties via store-item-data."
+ (with-fresh-drill-entry
+ (with-fixed-now
+ (org-drill-smart-reschedule 5 7))
+ (should (org-entry-get (point) "DRILL_LAST_INTERVAL"))
+ (should (org-entry-get (point) "DRILL_TOTAL_REPEATS"))
+ (should (org-entry-get (point) "DRILL_EASE"))))
+
+(ert-deftest test-org-drill-smart-reschedule-increments-total-repeats ()
+ "Each rating increments DRILL_TOTAL_REPEATS."
+ (with-fresh-drill-entry
+ (with-fixed-now
+ (org-drill-smart-reschedule 4 7)
+ (let ((after-first (string-to-number
+ (org-entry-get (point) "DRILL_TOTAL_REPEATS"))))
+ (org-drill-smart-reschedule 4 7)
+ (let ((after-second (string-to-number
+ (org-entry-get (point) "DRILL_TOTAL_REPEATS"))))
+ (should (= (1+ after-first) after-second)))))))
+
+(provide 'test-org-drill-smart-reschedule)
+
+;;; test-org-drill-smart-reschedule.el ends here