aboutsummaryrefslogtreecommitdiff
path: root/tests/test-org-drill-read-rating-key.el
blob: 2a54a2c72d610423b177178ce0c08cf1545ea27a (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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
;;; test-org-drill-read-rating-key.el --- Tests for --read-rating-key  -*- lexical-binding: t; -*-

;;; Commentary:
;; Tests for `org-drill--read-rating-key', the post-presentation key loop
;; shared by `org-drill-reschedule' and `org-drill-leitner-rebox'.
;;
;; The loop reads keys via `org-drill--read-key-sequence' until it gets a
;; 0-5 char, edit, quit, or C-g.  Three input shapes are recognized:
;;
;; - String (a typed character)
;; - Vector starting with a symbol (arrow / page keys)
;; - Vector starting with an event list (mouse wheel)

;;; Code:

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

(defmacro with-keys-and-buffer (keys &rest body)
  "Run BODY with `org-drill--read-key-sequence' returning successive KEYS.
KEYS is a list — each call returns the next element."
  (declare (indent 1))
  `(let ((__remaining__ ,keys))
     (with-temp-buffer
       (insert "* Drill :drill:\nsome body line\nanother line\n")
       (goto-char (point-min))
       (cl-letf (((symbol-function 'org-drill--read-key-sequence)
                  (lambda (&rest _)
                    (or (pop __remaining__)
                        (error "Test ran out of mock keys"))))
                 ((symbol-function 'org-set-tags-command) #'ignore))
         ,@body))))

(ert-deftest test-read-rating-key-direct-numeric-returns-char ()
  "A string input \"3\" makes the loop return the ?3 character."
  (with-keys-and-buffer '("3")
    (should (eql ?3 (org-drill--read-rating-key nil "help")))))

(ert-deftest test-read-rating-key-quit-key-returns-quit ()
  "Quit key terminates the loop and returns the quit char."
  (with-keys-and-buffer (list (string org-drill--quit-key))
    (should (eql org-drill--quit-key
                 (org-drill--read-rating-key nil "help")))))

(ert-deftest test-read-rating-key-edit-key-returns-edit ()
  "Edit key terminates the loop and returns the edit char."
  (with-keys-and-buffer (list (string org-drill--edit-key))
    (should (eql org-drill--edit-key
                 (org-drill--read-rating-key nil "help")))))

(ert-deftest test-read-rating-key-arrow-key-then-numeric-returns-numeric ()
  "An arrow-key vector is processed (no terminal effect) and the next
numeric input ends the loop."
  (with-keys-and-buffer (list (vector 'down) "5")
    (should (eql ?5 (org-drill--read-rating-key nil "help")))))

(ert-deftest test-read-rating-key-handles-all-navigation-keys ()
  "All six navigation keys (up/down/left/right/prior/next) are accepted
without terminating the loop, then a numeric ends it."
  (cl-letf (((symbol-function 'scroll-down) #'ignore)
            ((symbol-function 'scroll-up) #'ignore))
    (dolist (key '(up left right prior next))
      (with-keys-and-buffer (list (vector key) "1")
        (should (eql ?1 (org-drill--read-rating-key nil "help")))))))

(ert-deftest test-read-rating-key-wheel-event-then-numeric ()
  "A wheel-event vector is dispatched without terminating; loop ends on
the next numeric character."
  (let ((scroll-called nil))
    (cl-letf (((symbol-function 'mwheel-scroll)
               (lambda (&rest _) (setq scroll-called t))))
      (with-keys-and-buffer (list (vector '(wheel-up nil)) "0")
        (should (eql ?0 (org-drill--read-rating-key nil "help")))))))

(ert-deftest test-read-rating-key-help-key-shows-help-then-numeric ()
  "Pressing the help key on the first iteration causes the next prompt to
include the rating-help-block, then numeric ends the loop."
  (let ((seen-prompts nil))
    (cl-letf (((symbol-function 'org-drill--read-key-sequence)
               (let ((counter 0)
                     (keys (list (string org-drill--help-key) "4")))
                 (lambda (prompt)
                   (push prompt seen-prompts)
                   (cl-incf counter)
                   (pop keys))))
              ((symbol-function 'org-set-tags-command) #'ignore))
      (with-temp-buffer
        (insert "* Drill :drill:\nbody\n")
        (goto-char (point-min))
        (should (eql ?4 (org-drill--read-rating-key nil "RATING-HELP")))
        ;; Second prompt (after help key) carries the help block.
        (should (cl-some (lambda (p) (string-match-p "RATING-HELP" p))
                         seen-prompts))))))

(ert-deftest test-read-rating-key-tags-key-invokes-tags-command ()
  "If the tags key is used to terminate the loop, org-set-tags-command runs."
  (let ((tags-called nil))
    (cl-letf (((symbol-function 'org-drill--read-key-sequence)
               (let ((keys (list (string org-drill--tags-key))))
                 (lambda (&rest _) (pop keys))))
              ((symbol-function 'org-set-tags-command)
               (lambda (&rest _) (setq tags-called t))))
      ;; tags-key is not in the loop's terminal-set, so the loop would spin —
      ;; but `--read-rating-key' terminates only on quit/edit/C-g/0-5, so
      ;; tags-key alone won't end the loop.  We feed quit-key as a follow-up.
      (cl-letf (((symbol-function 'org-drill--read-key-sequence)
                 (let ((keys (list (string org-drill--tags-key)
                                   (string org-drill--quit-key))))
                   (lambda (&rest _) (pop keys)))))
        (with-temp-buffer
          (insert "* Drill :drill:\nbody\n")
          (org-drill--read-rating-key nil "help")
          (should tags-called))))))

(ert-deftest test-read-rating-key-typed-answer-shown-in-prompt ()
  "A non-nil typed-answer arg appears in the prompt as 'Your answer: ...'."
  (let ((seen-prompt nil))
    (cl-letf (((symbol-function 'org-drill--read-key-sequence)
               (lambda (prompt) (setq seen-prompt prompt) "0"))
              ((symbol-function 'org-set-tags-command) #'ignore))
      (with-temp-buffer
        (org-drill--read-rating-key "my-typed-answer" "help"))
      (should (string-match-p "Your answer: my-typed-answer" seen-prompt)))))

(provide 'test-org-drill-read-rating-key)
;;; test-org-drill-read-rating-key.el ends here