diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-05 04:02:35 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-05 04:02:35 -0500 |
| commit | 94ab747731c24ea2170ecd287980a272d9de244c (patch) | |
| tree | 8643782011e6e3e3a163125d86b552a9411e59eb | |
| parent | d3fdad57f9015f1bdd37489e7239b5347f45b535 (diff) | |
| download | org-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).
| -rw-r--r-- | tests/test-org-drill-entry-properties.el | 214 |
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 |
