diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-05 04:21:23 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-05 04:21:23 -0500 |
| commit | 50b49ae88b4b9ebcdf7295a018dc79f04ba3790b (patch) | |
| tree | e26e71c800fe1ee96a46b2887bab411f1ff92863 | |
| parent | 39a465d54964873980b1b3fe147e7e640bf74985 (diff) | |
| download | org-drill-50b49ae88b4b9ebcdf7295a018dc79f04ba3790b.tar.gz org-drill-50b49ae88b4b9ebcdf7295a018dc79f04ba3790b.zip | |
test: add list-utility, hide-comments/drawers, and Leitner promotion coverage
17 ERT tests covering:
- org-drill-swap: distinct indices, same-index no-op, end-to-start
- org-drill-shuffle: preserves element multiset, empty list, singleton
- org-drill-pop-random: removes-one, nil-on-empty, empties singleton
- org-drill-hide-comments: per-line overlay, no-op on comment-free buffer
- org-drill-hide-drawers: PROPERTIES drawer, multiple drawers, no-op
on drawer-free entry
- org-drill-leitner-promote: box-N → box-(N+1), graduation at box 5
(with and without org-drill-leitner-promote-to-drill-p flag)
| -rw-r--r-- | tests/test-org-drill-utilities-and-leitner.el | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/tests/test-org-drill-utilities-and-leitner.el b/tests/test-org-drill-utilities-and-leitner.el new file mode 100644 index 0000000..cc0157c --- /dev/null +++ b/tests/test-org-drill-utilities-and-leitner.el @@ -0,0 +1,175 @@ +;;; test-org-drill-utilities-and-leitner.el --- Tests for list utils, hide helpers, Leitner promote -*- lexical-binding: t; -*- + +;;; Commentary: +;; Tests for a grab-bag of small helpers: +;; +;; - `org-drill-swap' / `org-drill-shuffle': in-place list utilities +;; - `org-drill-pop-random': macro that removes a random element +;; - `org-drill-hide-comments' / `org-drill-hide-drawers': overlay hiders +;; for buffer noise the user shouldn't see during a drill +;; - `org-drill-leitner-promote': move a card forward in the Leitner +;; box system, including the special "graduate to drill" jump at box 5 + +;;; Code: + +(require 'ert) +(require 'cl-lib) +(require 'org) +(require 'org-drill) + +;;;; Helpers + +(defun count-overlays-of-category (cat) + (let ((n 0)) + (dolist (ovl (overlays-in (point-min) (point-max))) + (when (eql cat (overlay-get ovl 'category)) + (cl-incf n))) + n)) + +;;;; org-drill-swap + +(ert-deftest test-org-drill-swap-normal-distinct-indices () + "Swapping indices 0 and 2 in (a b c d) gives (c b a d)." + (let ((lst (list 'a 'b 'c 'd))) + (org-drill-swap lst 0 2) + (should (equal '(c b a d) lst)))) + +(ert-deftest test-org-drill-swap-same-index-is-noop () + "Swapping an index with itself leaves the list unchanged." + (let ((lst (list 'a 'b 'c))) + (org-drill-swap lst 1 1) + (should (equal '(a b c) lst)))) + +(ert-deftest test-org-drill-swap-end-and-start () + (let ((lst (list 1 2 3 4 5))) + (org-drill-swap lst 0 4) + (should (equal '(5 2 3 4 1) lst)))) + +;;;; org-drill-shuffle + +(ert-deftest test-org-drill-shuffle-preserves-element-set () + "After shuffling, the multiset of elements is unchanged." + (let* ((original '(1 2 3 4 5 6 7 8 9 10)) + (shuffled (org-drill-shuffle (copy-sequence original)))) + (should (equal (sort (copy-sequence shuffled) #'<) + original)))) + +(ert-deftest test-org-drill-shuffle-empty-list-is-empty () + (should (null (org-drill-shuffle nil))) + (should (equal '() (org-drill-shuffle (list))))) + +(ert-deftest test-org-drill-shuffle-single-element-unchanged () + (should (equal '(42) (org-drill-shuffle (list 42))))) + +;;;; org-drill-pop-random (macro) + +(ert-deftest test-org-drill-pop-random-removes-one-element () + (let ((lst (list 'a 'b 'c 'd))) + (let ((popped (org-drill-pop-random lst))) + (should (memq popped '(a b c d))) + (should (= 3 (length lst))) + (should-not (memq popped lst))))) + +(ert-deftest test-org-drill-pop-random-on-nil-returns-nil () + (let ((lst nil)) + (should (null (org-drill-pop-random lst))))) + +(ert-deftest test-org-drill-pop-random-on-singleton-empties-list () + (let ((lst (list 'only))) + (should (eq 'only (org-drill-pop-random lst))) + (should (null lst)))) + +;;;; org-drill-hide-comments + +(ert-deftest test-org-drill-hide-comments-hides-each-comment-line () + "Each `^#' comment line gets its own hidden-text overlay." + (with-temp-buffer + (insert "# first comment\n# second comment\nactual body\n") + (goto-char (point-min)) + (org-drill-hide-comments) + (should (= 2 (count-overlays-of-category 'org-drill-hidden-text-overlay))))) + +(ert-deftest test-org-drill-hide-comments-no-comments-no-overlays () + (with-temp-buffer + (insert "no comments here\njust regular text\n") + (goto-char (point-min)) + (org-drill-hide-comments) + (should (= 0 (count-overlays-of-category 'org-drill-hidden-text-overlay))))) + +;;;; org-drill-hide-drawers + +(ert-deftest test-org-drill-hide-drawers-hides-properties-drawer () + "PROPERTIES drawer becomes a hidden-text overlay during drilling." + (with-temp-buffer + (let ((org-startup-folded nil)) + (insert "* Question :drill:\n:PROPERTIES:\n:ID: x\n:END:\nbody\n") + (org-mode) + (goto-char (point-min)) + (org-drill-hide-drawers) + (should (>= (count-overlays-of-category 'org-drill-hidden-text-overlay) 1))))) + +(ert-deftest test-org-drill-hide-drawers-handles-multiple-drawers () + "Multiple drawers each get an overlay." + (with-temp-buffer + (let ((org-startup-folded nil)) + (insert "* Question :drill:\n:PROPERTIES:\n:ID: x\n:END:\n:LOGBOOK:\nentry\n:END:\nbody\n") + (org-mode) + (goto-char (point-min)) + (org-drill-hide-drawers) + (should (>= (count-overlays-of-category 'org-drill-hidden-text-overlay) 2))))) + +(ert-deftest test-org-drill-hide-drawers-no-drawer-no-overlay () + (with-temp-buffer + (let ((org-startup-folded nil)) + (insert "* Question :drill:\nbody only\n") + (org-mode) + (goto-char (point-min)) + (org-drill-hide-drawers) + (should (= 0 (count-overlays-of-category 'org-drill-hidden-text-overlay)))))) + +;;;; org-drill-leitner-promote + +(ert-deftest test-org-drill-leitner-promote-non-graduating-increments-box () + "Promotion from box 1 → 2, 2 → 3, etc. No tag change, just a property bump." + (with-temp-buffer + (let ((org-startup-folded nil)) + (insert "* Question :leitner:\n:PROPERTIES:\n:DRILL_LEITNER_BOX: 1\n:END:\n") + (org-mode) + (goto-char (point-min)) + (org-drill-leitner-promote 1) + (should (equal "2" (org-entry-get (point) "DRILL_LEITNER_BOX"))) + ;; Tags unchanged. + (should (member "leitner" (org-get-tags nil t))) + (should-not (member "drill" (org-get-tags nil t)))))) + +(ert-deftest test-org-drill-leitner-promote-from-box-5-graduates-to-drill () + "Promotion from box 5 toggles `leitner' off and (with the flag) `drill' on." + (with-temp-buffer + (let ((org-startup-folded nil)) + (insert "* Question :leitner:\n:PROPERTIES:\n:DRILL_LEITNER_BOX: 5\n:END:\n") + (org-mode) + (goto-char (point-min)) + (let ((org-drill-leitner-promote-to-drill-p t) + (org-drill-leitner-completed 0)) + (org-drill-leitner-promote 5) + (should-not (member "leitner" (org-get-tags nil t))) + (should (member "drill" (org-get-tags nil t))) + (should (= 1 org-drill-leitner-completed)))))) + +(ert-deftest test-org-drill-leitner-promote-from-box-5-without-promote-flag () + "Without the promote-to-drill flag, only `leitner' tag is removed." + (with-temp-buffer + (let ((org-startup-folded nil)) + (insert "* Question :leitner:\n:PROPERTIES:\n:DRILL_LEITNER_BOX: 5\n:END:\n") + (org-mode) + (goto-char (point-min)) + (let ((org-drill-leitner-promote-to-drill-p nil) + (org-drill-leitner-completed 0)) + (org-drill-leitner-promote 5) + (should-not (member "leitner" (org-get-tags nil t))) + (should-not (member "drill" (org-get-tags nil t))) + (should (= 1 org-drill-leitner-completed)))))) + +(provide 'test-org-drill-utilities-and-leitner) + +;;; test-org-drill-utilities-and-leitner.el ends here |
