aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-05 04:02:35 -0500
committerCraig Jennings <c@cjennings.net>2026-05-05 04:02:35 -0500
commit94ab747731c24ea2170ecd287980a272d9de244c (patch)
tree8643782011e6e3e3a163125d86b552a9411e59eb /tests
parentd3fdad57f9015f1bdd37489e7239b5347f45b535 (diff)
downloadorg-drill-94ab747731c24ea2170ecd287980a272d9de244c.tar.gz
org-drill-94ab747731c24ea2170ecd287980a272d9de244c.zip
test: add unit tests for entry-property accessors
30 ERT tests covering org-drill-entry-last-quality, entry-failure-count, entry-average-quality, entry-last-interval, entry-repeats-since-fail, entry-total-repeats, entry-ease, entry-leech-p, and entry-new-p. Documents each function's missing-property fallback behavior — three distinct shapes: nil-by-default (last-quality, average-quality, ease), hardcoded-zero-by-default (failure-count, last-interval, repeats-since- fail, total-repeats), or computed from other state (new-p, leech-p).
Diffstat (limited to 'tests')
-rw-r--r--tests/test-org-drill-entry-properties.el214
1 files changed, 214 insertions, 0 deletions
diff --git a/tests/test-org-drill-entry-properties.el b/tests/test-org-drill-entry-properties.el
new file mode 100644
index 0000000..5ee2dd1
--- /dev/null
+++ b/tests/test-org-drill-entry-properties.el
@@ -0,0 +1,214 @@
+;;; test-org-drill-entry-properties.el --- Tests for entry property accessors -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Unit tests for the small org-property reader functions that surface a
+;; drill entry's persisted state:
+;;
+;; - `org-drill-entry-last-quality'
+;; - `org-drill-entry-failure-count'
+;; - `org-drill-entry-average-quality'
+;; - `org-drill-entry-last-interval'
+;; - `org-drill-entry-repeats-since-fail'
+;; - `org-drill-entry-total-repeats'
+;; - `org-drill-entry-ease'
+;; - `org-drill-entry-leech-p'
+;; - `org-drill-entry-new-p'
+;;
+;; All but `entry-leech-p' read a single DRILL_* org-mode property and parse
+;; it as a number, with a configurable default when the property is absent.
+;; `entry-leech-p' checks for the "leech" tag. `entry-new-p' returns t when
+;; the entry has no SCHEDULED time stamp.
+
+;;; Code:
+
+(require 'ert)
+(require 'org)
+(require 'org-drill)
+
+;;;; Helpers
+
+(defmacro with-drill-entry-fixture (properties &rest body)
+ "Run BODY at point on a drill-tagged entry whose PROPERTIES are set.
+PROPERTIES is a list of (NAME . VALUE) cons cells. Each value is set
+via `org-set-property'."
+ (declare (indent 1))
+ `(with-temp-buffer
+ (let ((org-startup-folded nil))
+ (insert "* Question :drill:\n")
+ (org-mode)
+ (goto-char (point-min))
+ (dolist (prop ,properties)
+ (org-set-property (car prop) (cdr prop)))
+ (goto-char (point-min))
+ ,@body)))
+
+(defmacro with-non-drill-entry-fixture (&rest body)
+ "Run BODY at point on a heading without the :drill: tag."
+ (declare (indent 0))
+ `(with-temp-buffer
+ (let ((org-startup-folded nil))
+ (insert "* Plain heading\n")
+ (org-mode)
+ (goto-char (point-min))
+ ,@body)))
+
+;;;; org-drill-entry-last-quality
+
+(ert-deftest test-org-drill-entry-last-quality-normal-property-set ()
+ (with-drill-entry-fixture '(("DRILL_LAST_QUALITY" . "4"))
+ (should (equal 4 (org-drill-entry-last-quality)))))
+
+(ert-deftest test-org-drill-entry-last-quality-normal-property-zero ()
+ (with-drill-entry-fixture '(("DRILL_LAST_QUALITY" . "0"))
+ (should (equal 0 (org-drill-entry-last-quality)))))
+
+(ert-deftest test-org-drill-entry-last-quality-boundary-no-property-no-default ()
+ (with-drill-entry-fixture nil
+ (should (null (org-drill-entry-last-quality)))))
+
+(ert-deftest test-org-drill-entry-last-quality-boundary-no-property-with-default ()
+ (with-drill-entry-fixture nil
+ (should (equal 'no-quality (org-drill-entry-last-quality 'no-quality)))))
+
+(ert-deftest test-org-drill-entry-last-quality-normal-property-overrides-default ()
+ "When the property is set the default is ignored."
+ (with-drill-entry-fixture '(("DRILL_LAST_QUALITY" . "3"))
+ (should (equal 3 (org-drill-entry-last-quality 'fallback)))))
+
+;;;; org-drill-entry-failure-count
+
+(ert-deftest test-org-drill-entry-failure-count-normal-property-set ()
+ (with-drill-entry-fixture '(("DRILL_FAILURE_COUNT" . "7"))
+ (should (equal 7 (org-drill-entry-failure-count)))))
+
+(ert-deftest test-org-drill-entry-failure-count-boundary-no-property-returns-zero ()
+ "Failure-count's missing-property fallback is hardcoded to 0, not nil."
+ (with-drill-entry-fixture nil
+ (should (equal 0 (org-drill-entry-failure-count)))))
+
+(ert-deftest test-org-drill-entry-failure-count-boundary-property-zero ()
+ (with-drill-entry-fixture '(("DRILL_FAILURE_COUNT" . "0"))
+ (should (equal 0 (org-drill-entry-failure-count)))))
+
+;;;; org-drill-entry-average-quality
+
+(ert-deftest test-org-drill-entry-average-quality-normal-property-set ()
+ (with-drill-entry-fixture '(("DRILL_AVERAGE_QUALITY" . "3.75"))
+ (should (equal 3.75 (org-drill-entry-average-quality)))))
+
+(ert-deftest test-org-drill-entry-average-quality-boundary-no-property-no-default ()
+ (with-drill-entry-fixture nil
+ (should (null (org-drill-entry-average-quality)))))
+
+(ert-deftest test-org-drill-entry-average-quality-boundary-no-property-with-default ()
+ (with-drill-entry-fixture nil
+ (should (equal 2.5 (org-drill-entry-average-quality 2.5)))))
+
+;;;; org-drill-entry-last-interval
+
+(ert-deftest test-org-drill-entry-last-interval-normal-property-set ()
+ (with-drill-entry-fixture '(("DRILL_LAST_INTERVAL" . "14"))
+ (should (equal 14 (org-drill-entry-last-interval)))))
+
+(ert-deftest test-org-drill-entry-last-interval-normal-fractional-interval ()
+ (with-drill-entry-fixture '(("DRILL_LAST_INTERVAL" . "0.5"))
+ (should (equal 0.5 (org-drill-entry-last-interval)))))
+
+(ert-deftest test-org-drill-entry-last-interval-boundary-no-property-default-zero ()
+ "Last-interval's missing-property fallback is 0, not nil."
+ (with-drill-entry-fixture nil
+ (should (equal 0 (org-drill-entry-last-interval)))))
+
+(ert-deftest test-org-drill-entry-last-interval-boundary-no-property-with-default ()
+ (with-drill-entry-fixture nil
+ (should (equal 99 (org-drill-entry-last-interval 99)))))
+
+;;;; org-drill-entry-repeats-since-fail
+
+(ert-deftest test-org-drill-entry-repeats-since-fail-normal-property-set ()
+ (with-drill-entry-fixture '(("DRILL_REPEATS_SINCE_FAIL" . "5"))
+ (should (equal 5 (org-drill-entry-repeats-since-fail)))))
+
+(ert-deftest test-org-drill-entry-repeats-since-fail-boundary-no-property-default-zero ()
+ (with-drill-entry-fixture nil
+ (should (equal 0 (org-drill-entry-repeats-since-fail)))))
+
+(ert-deftest test-org-drill-entry-repeats-since-fail-boundary-no-property-with-default ()
+ (with-drill-entry-fixture nil
+ (should (equal 12 (org-drill-entry-repeats-since-fail 12)))))
+
+;;;; org-drill-entry-total-repeats
+
+(ert-deftest test-org-drill-entry-total-repeats-normal-property-set ()
+ (with-drill-entry-fixture '(("DRILL_TOTAL_REPEATS" . "23"))
+ (should (equal 23 (org-drill-entry-total-repeats)))))
+
+(ert-deftest test-org-drill-entry-total-repeats-boundary-no-property-default-zero ()
+ (with-drill-entry-fixture nil
+ (should (equal 0 (org-drill-entry-total-repeats)))))
+
+(ert-deftest test-org-drill-entry-total-repeats-boundary-no-property-with-default ()
+ (with-drill-entry-fixture nil
+ (should (equal 100 (org-drill-entry-total-repeats 100)))))
+
+;;;; org-drill-entry-ease
+
+(ert-deftest test-org-drill-entry-ease-normal-property-set ()
+ (with-drill-entry-fixture '(("DRILL_EASE" . "2.5"))
+ (should (equal 2.5 (org-drill-entry-ease)))))
+
+(ert-deftest test-org-drill-entry-ease-boundary-no-property-no-default ()
+ (with-drill-entry-fixture nil
+ (should (null (org-drill-entry-ease)))))
+
+(ert-deftest test-org-drill-entry-ease-boundary-no-property-with-default ()
+ (with-drill-entry-fixture nil
+ (should (equal 1.3 (org-drill-entry-ease 1.3)))))
+
+;;;; org-drill-entry-leech-p
+
+(ert-deftest test-org-drill-entry-leech-p-normal-leech-tag-on-drill-entry-returns-t ()
+ (with-temp-buffer
+ (let ((org-startup-folded nil))
+ (insert "* Hard one :drill:leech:\n")
+ (org-mode)
+ (goto-char (point-min))
+ (should (org-drill-entry-leech-p)))))
+
+(ert-deftest test-org-drill-entry-leech-p-normal-no-leech-tag-returns-nil ()
+ (with-drill-entry-fixture nil
+ (should-not (org-drill-entry-leech-p))))
+
+(ert-deftest test-org-drill-entry-leech-p-error-leech-tag-without-drill-tag ()
+ "An entry tagged leech but without the drill tag is not a leech (must be a drill entry first)."
+ (with-temp-buffer
+ (let ((org-startup-folded nil))
+ (insert "* Just leech :leech:\n")
+ (org-mode)
+ (goto-char (point-min))
+ (should-not (org-drill-entry-leech-p)))))
+
+;;;; org-drill-entry-new-p
+
+(ert-deftest test-org-drill-entry-new-p-normal-no-scheduled-stamp-returns-t ()
+ "A drill entry with no SCHEDULED timestamp is new."
+ (with-drill-entry-fixture nil
+ (should (org-drill-entry-new-p))))
+
+(ert-deftest test-org-drill-entry-new-p-normal-with-scheduled-stamp-returns-nil ()
+ "A drill entry with a SCHEDULED timestamp is not new."
+ (with-temp-buffer
+ (let ((org-startup-folded nil))
+ (insert "* Question :drill:\nSCHEDULED: <2026-05-05 Tue>\n")
+ (org-mode)
+ (goto-char (point-min))
+ (should-not (org-drill-entry-new-p)))))
+
+(ert-deftest test-org-drill-entry-new-p-error-non-drill-entry-returns-nil ()
+ "A non-drill entry is not \"new\" — there's no drill state to consider."
+ (with-non-drill-entry-fixture
+ (should-not (org-drill-entry-new-p))))
+
+(provide 'test-org-drill-entry-properties)
+
+;;; test-org-drill-entry-properties.el ends here