test-org-agenda.el 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. ;;; test-org-agenda.el --- Tests for org-agenda.el -*- lexical-binding: t ; -*-
  2. ;; Copyright (C) 2017, 2019 Marco Wahl
  3. ;; Author: Marco Wahl <marcowahlsoft@gmail.com>
  4. ;; This program is free software; you can redistribute it and/or modify
  5. ;; it under the terms of the GNU General Public License as published by
  6. ;; the Free Software Foundation, either version 3 of the License, or
  7. ;; (at your option) any later version.
  8. ;; This program is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;; GNU General Public License for more details.
  12. ;; You should have received a copy of the GNU General Public License
  13. ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. ;;; Commentary:
  15. ;; Unit tests for Org Agenda.
  16. ;;; Code:
  17. (require 'org-test "../testing/org-test")
  18. (require 'org-agenda)
  19. (eval-and-compile (require 'cl-lib))
  20. ;; General auxiliaries
  21. (defun org-test-agenda--agenda-buffers ()
  22. "Return agenda buffers in a list."
  23. (cl-remove-if-not (lambda (x)
  24. (with-current-buffer x
  25. (eq major-mode 'org-agenda-mode)))
  26. (buffer-list)))
  27. (defun org-test-agenda--kill-all-agendas ()
  28. "Kill all agenda buffers."
  29. (mapc #'kill-buffer
  30. (org-test-agenda--agenda-buffers)))
  31. (defmacro org-test-agenda-with-agenda (text &rest body)
  32. (declare (indent 1))
  33. `(org-test-with-temp-text-in-file ,text
  34. (let ((org-agenda-files `(,buffer-file-name)))
  35. ,@body
  36. (org-test-agenda--kill-all-agendas))))
  37. ;; Test the Agenda
  38. (ert-deftest test-org-agenda/empty ()
  39. "Empty agenda."
  40. (cl-assert (not org-agenda-sticky) nil "precondition violation")
  41. (cl-assert (not (org-test-agenda--agenda-buffers))
  42. nil "precondition violation")
  43. (let ((org-agenda-span 'day)
  44. org-agenda-files)
  45. (org-agenda-list)
  46. (set-buffer org-agenda-buffer-name)
  47. (should (= 2 (count-lines (point-min) (point-max)))))
  48. (org-test-agenda--kill-all-agendas))
  49. (ert-deftest test-org-agenda/one-line ()
  50. "One informative line in the agenda."
  51. (cl-assert (not org-agenda-sticky) nil "precondition violation")
  52. (cl-assert (not (org-test-agenda--agenda-buffers))
  53. nil "precondition violation")
  54. (let ((org-agenda-span 'day)
  55. (org-agenda-files `(,(expand-file-name "examples/agenda-file.org"
  56. org-test-dir))))
  57. ;; NOTE: Be aware that `org-agenda-list' may or may not display
  58. ;; past scheduled items depending whether the date is today
  59. ;; `org-today' or not.
  60. (org-agenda-list nil "<2017-03-10 Fri>")
  61. (set-buffer org-agenda-buffer-name)
  62. (should (= 3 (count-lines (point-min) (point-max)))))
  63. (org-test-agenda--kill-all-agendas))
  64. (ert-deftest test-org-agenda/scheduled-non-todo ()
  65. "One informative line in the agenda from scheduled non-todo-keyword-item."
  66. (cl-assert (not org-agenda-sticky) nil "precondition violation")
  67. (cl-assert (not (org-test-agenda--agenda-buffers))
  68. nil "precondition violation")
  69. (let ((org-agenda-span 'day)
  70. (org-agenda-files `(,(expand-file-name "examples/agenda-file.org"
  71. org-test-dir))))
  72. ;; NOTE: Be aware that `org-agenda-list' may or may not display
  73. ;; past scheduled items depending whether the date is today
  74. ;; `org-today' or not.
  75. (org-agenda-list nil "<2017-07-19 Wed>")
  76. (set-buffer org-agenda-buffer-name)
  77. (should
  78. (progn (goto-line 3)
  79. (looking-at " *agenda-file:Scheduled: *test agenda"))))
  80. (org-test-agenda--kill-all-agendas))
  81. (ert-deftest test-org-agenda/non-scheduled-re-matces ()
  82. "Make sure that scheduled-looking elements do not appear in agenda.
  83. See https://list.orgmode.org/20220101200103.GB29829@itccanarias.org/T/#t."
  84. (cl-assert (not org-agenda-sticky) nil "precondition violation")
  85. (cl-assert (not (org-test-agenda--agenda-buffers))
  86. nil "precondition violation")
  87. (let ((org-agenda-span 'day)
  88. (org-agenda-files `(,(expand-file-name "examples/agenda-file.org"
  89. org-test-dir))))
  90. ;; NOTE: Be aware that `org-agenda-list' may or may not display
  91. ;; past scheduled items depending whether the date is today
  92. ;; `org-today' or not.
  93. (org-agenda-list nil "<2022-01-03 Mon>")
  94. (set-buffer org-agenda-buffer-name)
  95. (should (= 2 (count-lines (point-min) (point-max)))))
  96. (org-test-agenda--kill-all-agendas))
  97. (ert-deftest test-org-agenda/property-timestamp ()
  98. "Match timestamps inside property drawer.
  99. See https://list.orgmode.org/06d301d83d9e$f8b44340$ea1cc9c0$@tomdavey.com"
  100. (cl-assert (not org-agenda-sticky) nil "precondition violation")
  101. (cl-assert (not (org-test-agenda--agenda-buffers))
  102. nil "precondition violation")
  103. (let ((org-agenda-span 'day)
  104. (org-agenda-files `(,(expand-file-name "examples/agenda-file.org"
  105. org-test-dir))))
  106. ;; NOTE: Be aware that `org-agenda-list' may or may not display
  107. ;; past scheduled items depending whether the date is today
  108. ;; `org-today' or not.
  109. (org-agenda-list nil "<2022-03-22 Tue>")
  110. (set-buffer org-agenda-buffer-name)
  111. (should (= 3 (count-lines (point-min) (point-max))))
  112. ;; NOTE: Be aware that `org-agenda-list' may or may not display
  113. ;; past scheduled items depending whether the date is today
  114. ;; `org-today' or not.
  115. (org-agenda-list nil "<2022-03-25 Fri>")
  116. (set-buffer org-agenda-buffer-name)
  117. (should (= 3 (count-lines (point-min) (point-max)))))
  118. (org-test-agenda--kill-all-agendas))
  119. (ert-deftest test-org-agenda/set-priority ()
  120. "One informative line in the agenda. Check that org-agenda-priority updates the agenda."
  121. (cl-assert (not org-agenda-sticky) nil "precondition violation")
  122. (cl-assert (not (org-test-agenda--agenda-buffers))
  123. nil "precondition violation")
  124. (let ((org-agenda-span 'day)
  125. (org-agenda-files `(,(expand-file-name "examples/agenda-file.org"
  126. org-test-dir))))
  127. ;; NOTE: Be aware that `org-agenda-list' may or may not display
  128. ;; past scheduled items depending whether the date is today
  129. ;; `org-today' or not.
  130. (org-agenda-list nil "<2017-07-19 Wed>")
  131. (set-buffer org-agenda-buffer-name)
  132. (should
  133. (progn (goto-line 3)
  134. (org-agenda-priority ?B)
  135. (looking-at-p " *agenda-file:Scheduled: *\\[#B\\] test agenda"))))
  136. (org-test-agenda--kill-all-agendas))
  137. (ert-deftest test-org-agenda/sticky-agenda-name ()
  138. "Agenda buffer name after having created one sticky agenda buffer."
  139. (cl-assert (not org-agenda-sticky) nil "precondition violation")
  140. (cl-assert (not (org-test-agenda--agenda-buffers))
  141. nil "precondition violation")
  142. (let ((org-agenda-span 'day)
  143. (buf (get-buffer org-agenda-buffer-name))
  144. org-agenda-files)
  145. (when buf (kill-buffer buf))
  146. (dolist (fn '(org-agenda-list org-todo-list))
  147. (org-test-with-temp-text "<2017-03-17 Fri>"
  148. (org-follow-timestamp-link)) ;creates a sticky agenda
  149. (org-test-agenda--kill-all-agendas)
  150. (funcall fn)
  151. (should (= 1 (length (org-test-agenda--agenda-buffers))))
  152. (should (string= "*Org Agenda*"
  153. (buffer-name (car (org-test-agenda--agenda-buffers)))))))
  154. (org-test-agenda--kill-all-agendas))
  155. (ert-deftest test-org-agenda/sticky-agenda-name-after-reload ()
  156. "Agenda buffer name of sticky agenda after reload."
  157. (cl-assert (not org-agenda-sticky) nil "precondition violation")
  158. (cl-assert (not (org-test-agenda--agenda-buffers))
  159. nil "precondition violation")
  160. (org-toggle-sticky-agenda)
  161. (let (org-agenda-files)
  162. (org-agenda-list)
  163. (let* ((agenda-buffer-name
  164. (progn
  165. (cl-assert (= 1 (length (org-test-agenda--agenda-buffers))))
  166. (buffer-name (car (org-test-agenda--agenda-buffers))))))
  167. (set-buffer agenda-buffer-name)
  168. (org-agenda-redo)
  169. (should (= 1 (length (org-test-agenda--agenda-buffers))))
  170. (should (string= agenda-buffer-name
  171. (buffer-name (car (org-test-agenda--agenda-buffers)))))))
  172. (org-toggle-sticky-agenda)
  173. (org-test-agenda--kill-all-agendas))
  174. (ert-deftest test-org-agenda/sticky-agenda-filter-preset ()
  175. "Update sticky agenda buffers properly with preset of filters."
  176. (unless org-agenda-sticky
  177. (org-toggle-sticky-agenda))
  178. (org-test-agenda-with-agenda "* TODO Foo"
  179. (org-set-property "CATEGORY" "foo")
  180. (let ((org-agenda-custom-commands
  181. '(("f" "foo: multi-command"
  182. ((tags-todo "+CATEGORY=\"foo\"")
  183. (alltodo ""))
  184. ((org-agenda-category-filter-preset '("+foo"))))
  185. ("b" "bar: multi-command"
  186. ((tags-todo "+CATEGORY=\"bar\"")
  187. (alltodo ""))
  188. ((org-agenda-category-filter-preset '("+bar"))))
  189. ("f1" "foo: single-command"
  190. tags-todo "+CATEGORY=\"foo\""
  191. ((org-agenda-category-filter-preset '("+foo"))))
  192. ("b1" "bar: single-command"
  193. tags-todo "+CATEGORY=\"bar\""
  194. ((org-agenda-category-filter-preset '("+bar"))))
  195. ("f2" "foo: single-command"
  196. alltodo "" ((org-agenda-category-filter-preset '("+foo"))))
  197. ("b2" "bar: single-command"
  198. alltodo "" ((org-agenda-category-filter-preset '("+bar")))))))
  199. (org-agenda nil "f")
  200. (org-agenda nil "b")
  201. (set-buffer "*Org Agenda(f)*")
  202. (org-agenda-redo)
  203. (goto-char (point-min))
  204. (should (not (invisible-p (1- (search-forward "TODO Foo")))))
  205. (org-test-agenda--kill-all-agendas)
  206. (org-agenda nil "f1")
  207. (org-agenda nil "b1")
  208. (set-buffer "*Org Agenda(f1:+CATEGORY=\"foo\")*")
  209. (org-agenda-redo)
  210. (goto-char (point-min))
  211. (should (not (invisible-p (1- (search-forward "TODO Foo")))))
  212. (org-test-agenda--kill-all-agendas)
  213. (org-agenda nil "f2")
  214. (org-agenda nil "b2")
  215. (set-buffer "*Org Agenda(f2)*")
  216. (org-agenda-redo)
  217. (goto-char (point-min))
  218. (should (not (invisible-p (1- (search-forward "TODO Foo")))))))
  219. (org-toggle-sticky-agenda))
  220. (ert-deftest test-org-agenda/goto-date ()
  221. "Test `org-agenda-goto-date'."
  222. (unwind-protect
  223. (should
  224. (equal
  225. (time-to-days (org-time-string-to-time "2019-12-30"))
  226. (let ((org-agenda-files nil))
  227. (org-agenda-list nil nil 'day)
  228. (org-agenda-goto-date "2019-12-30")
  229. (get-text-property (point) 'day))))
  230. (org-test-agenda--kill-all-agendas)))
  231. ;; agenda redo
  232. (require 'face-remap)
  233. (ert-deftest test-org-agenda/rescale ()
  234. "Text scale survives `org-agenda-redo'."
  235. (org-test-agenda--kill-all-agendas)
  236. (unwind-protect
  237. (let ((org-agenda-span 'day)
  238. org-agenda-files)
  239. (org-agenda-list)
  240. (set-buffer org-agenda-buffer-name)
  241. (text-scale-mode)
  242. (text-scale-set 11)
  243. (cl-assert (and (boundp text-scale-mode) text-scale-mode))
  244. (org-agenda-redo)
  245. (should text-scale-mode)
  246. (should (= 11 text-scale-mode-amount)))
  247. (org-test-agenda--kill-all-agendas)))
  248. (ert-deftest test-org-agenda/redo-setting ()
  249. "Command settings survives `org-agenda-redo'."
  250. (org-test-agenda--kill-all-agendas)
  251. (let ((org-agenda-custom-commands
  252. '(("t" "TODOs" alltodo ""
  253. ((org-agenda-overriding-header "Test"))))))
  254. (org-agenda nil "t")
  255. (org-agenda-redo)
  256. (org-agenda-redo)
  257. (goto-char (point-min))
  258. (should (looking-at-p "Test")))
  259. (org-test-agenda--kill-all-agendas))
  260. (ert-deftest test-org-agenda/diary-inclusion ()
  261. "Diary inclusion happens."
  262. (org-test-agenda--kill-all-agendas)
  263. (let ((diary-file (expand-file-name "examples/diary-file" org-test-dir))
  264. (org-agenda-files `(,(expand-file-name "examples/agenda-file.org"
  265. org-test-dir)))
  266. (diary-date-forms '((month "[-/]" day "[^-/0-9]")
  267. (year "[-/]" month "[-/]" day "[^0-9]")
  268. (monthname " *" day "[^-0-9]")
  269. (year " *" monthname " *" day "[^0-9]")
  270. (dayname "\\W")))
  271. (org-agenda-span 'day)
  272. (org-agenda-include-diary t))
  273. ;; NOTE: Be aware that `org-agenda-list' may or may not display
  274. ;; past scheduled items depending whether the date is today
  275. ;; `org-today' or not.
  276. (org-agenda-list nil "<2019-01-08>")
  277. (should (search-forward "f0bcf0cd8bad93c1451bb6e1b2aaedef5cce7cbb" nil t))
  278. (org-test-agenda--kill-all-agendas)))
  279. ;; agenda bulk actions
  280. (ert-deftest test-org-agenda/bulk ()
  281. "Bulk actions are applied to marked items."
  282. (org-test-agenda-with-agenda "* TODO a\n* TODO b"
  283. (org-todo-list)
  284. (org-agenda-bulk-mark-all)
  285. (cl-letf (((symbol-function 'read-char-exclusive)
  286. (lambda () ?t))
  287. ((symbol-function 'completing-read)
  288. (lambda (&rest _rest) "DONE")))
  289. (org-agenda-bulk-action))
  290. (org-agenda-previous-item 99)
  291. (should (looking-at ".*DONE a"))
  292. (org-agenda-next-item 1)
  293. (should (looking-at ".*DONE b"))))
  294. (ert-deftest test-org-agenda/bulk-custom ()
  295. "Custom bulk actions are applied to all marked items."
  296. (org-test-agenda-with-agenda "* TODO a\n* TODO b"
  297. (org-todo-list)
  298. (org-agenda-bulk-mark-all)
  299. ;; Mock read functions
  300. (let* ((f-call-cnt 0)
  301. (org-agenda-bulk-custom-functions
  302. `((?P ,(lambda () (setq f-call-cnt (1+ f-call-cnt)))))))
  303. (cl-letf* (((symbol-function 'read-char-exclusive)
  304. (lambda () ?P)))
  305. (org-agenda-bulk-action)
  306. (should (= f-call-cnt 2))))))
  307. (ert-deftest test-org-agenda/bulk-custom-arg-func ()
  308. "Argument collection functions can be specified for custom bulk
  309. functions."
  310. (org-test-agenda-with-agenda "* TODO a\n* TODO b"
  311. (org-todo-list)
  312. (org-agenda-bulk-mark-all)
  313. (let* ((f-called-cnt 0)
  314. (arg-f-call-cnt 0)
  315. (f-called-args nil)
  316. (org-agenda-bulk-custom-functions
  317. `((?P
  318. ;; Custom bulk function
  319. ,(lambda (&rest args)
  320. (message "test")
  321. (setq f-called-cnt (1+ f-called-cnt)
  322. f-called-args args))
  323. ;; Argument collection function
  324. ,(lambda ()
  325. (setq arg-f-call-cnt (1+ arg-f-call-cnt))
  326. '(1 2 3))))))
  327. (cl-letf (((symbol-function 'read-char-exclusive)
  328. (lambda () ?P)))
  329. (org-agenda-bulk-action))
  330. (should (= f-called-cnt 2))
  331. (should (= arg-f-call-cnt 1))
  332. (should (equal f-called-args '(1 2 3))))))
  333. (provide 'test-org-agenda)
  334. ;;; test-org-agenda.el ends here