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
|