org-mode/testing/lisp/test-org-agenda.el

432 lines
16 KiB
EmacsLisp
Raw Normal View History

;;; test-org-agenda.el --- Tests for org-agenda.el -*- lexical-binding: t ; -*-
2019-01-01 10:50:56 +00:00
;; Copyright (C) 2017, 2019 Marco Wahl
;; Author: Marco Wahl <marcowahlsoft@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Unit tests for Org Agenda.
;;; Code:
* lisp/org-agenda.el: Use lexical-binding - Removed the global (defvar date) and (defvar entry) so as not to conflict with function arguments of that name. Instead I added such `defvar`s in the body of each of the functions where it seemed needed. - I added some FIXMEs for some issues I found along the way. - Added an `org-dlet` macro, just like I had done for `calendar-dlet`, but I also use `defvar` "manually" at some places, when splitting an existing `let` into a mix of `let`s and `dlet`s seemed too much trouble. - Removed uses of `org-let and `org-let2` not only because I consider them offensive to my sense of aesthetics but also because they're basically incompatible with lexical scoping. I replaced them with uses of `cl-progv` which are a bit more verbose. Maybe we should define some `org-progv` macro on top of `cl-progv` to make the code less verbose, but I didn't do that because I like the fact that the current code makes uses of `eval` a bit more obvious (since these behave differently with lexical scoping than with lexical binding, it seemed worthwhile). - Removed the use of `eval` in `org-store-agenda-views` which was only placed there in order to use a macro before it's defined (it would have been simpler/cleaner to just move that functions *after* the macro, but with the new code the problem doesn't occur any more anyway). - Replaced a few `(lambda...) with actual closures. Detailed changes follow: (date, entry): Don't declare as being globally dynbound. (org-agenda-format-date-aligned): Remove unused var `weekyear`. (org-agenda-mode): `run-mode-hooks` is always available nowadays. (org-agenda-undo): Remove unused var `last-undo-buffer`. (org-agenda): Rename arg to `keys` and then dyn-bind it as `org-keys`. Remove unused vars `buf` and `key`. (org-agenda): Use `pcase` and `cl-progv` instead of `org-let`. (org-let, org-let2): Mark as obsolete. (org-agenda-run-series): Use `cl-progv` instead of `org-let` and `org-let2`. (org-agenda-run-series): New function. (org--batch-agenda): New function extracted from `org-batch-agenda`. (org-batch-agenda): Use it. (org--batch-agenda-csv): New function extracted from `org-batch-agenda-csv`. (org-batch-agenda-csv): Use it. (org--batch-store-agenda-views): New function, extracted from `org-batch-store-agenda-views`. (org-store-agenda-views, org-batch-store-agenda-views): Use it. (org--batch-store-agenda-views): Use `cl-progv` instead of `org-eval-in-environment`. (org-agenda-write): Use `cl-progv` instead of `org-let`. Use `with-current-buffer`. (org-agenda-filter-any): Use `cl-some` instead of `eval`. (org-agenda-list): Remove unused var `e`. (org-search-view): η-reduce. (crm-separator): Declare var. (org-agenda-skip-if): Remove unused var `beg`. (org-agenda-list-stuck-projects): Use a closure rather than `(lambda..). (diary-modify-entry-list-string-function, diary-file-name-prefix) (diary-display-function): Declare vars. (org-diary): Declare `date` and `entry` as dynbound. (org-agenda-get-day-entries): Use `org-dlet`. (org-agenda-get-timestamps, org-agenda-get-progress) (org-agenda-get-deadlines, org-agenda-get-scheduled, org-agenda-get-blocks): Declare `date` as dynbound. (org-agenda-get-sexps, org-class): Declare `date` and `entry` as dynbound. (org-agenda-format-item): Declare the vars mentioned in `org-compile-prefix-format` as dyn-bound. Also binding `extra`, suggested by Kyle Meyer <kyle@kyleam.com>. (org-compile-prefix-format): Remove unused var `e`. Use `member` rather than or+equal. (org-set-sorting-strategy): Minor simplification. (org-entries-lessp): Use `org-dlet`. (org-agenda-redo): Declare var `org-agenda-tag-filter-while-redo`. (org-agenda-redo): Use `cl-progv` rather than `org-let`. (org-agenda-filter): Remove unused var `rpl-fn`. Use `org-pushnew-to-end` to replace `add-to-list` on lexical var. (org-agenda-filter-by-tag): Remove unused var `n`. (org-agenda-filter-apply): Use `org-dlet`. (org-agenda-compute-starting-span): Remove unused var `dg`. (org-agenda-forward-block): Remove unused var `pos`. (org-archive-from-agenda): Declare var. (org-agenda-refile): Remove unused var `pos`. (org-agenda-headline-snapshot-before-repeat): Declare var. (org-agenda-todo): Remove redundant use of `bound-and-true-p`. (org-agenda-add-note): Remove unused var `hdmarker` and unused `arg`. (org-agenda-change-all-lines): Remove unused var `pl`. (org-agenda-priority): Remove unused var `marker`. (org-agenda-set-effort): Remove unused var `newhead`. (org-agenda-schedule): Remove unused var `type`. (org-agenda-clock-cancel): Remove unused `arg`. (org-agenda-execute-calendar-command): Use `org-dlet`. (org-agenda-bulk-action): Use closures instead of `(lambda ...). (org-agenda-show-the-flagging-note): Remove unused vars `heading` and `newhead`. (org-agenda-remove-flag): Avoid `setq`. * testing/org-test.el (org--compile-when): New macro. (org-test-jump): Use it so compilation doesn't fail or generate broken code when `jump` is not available. * testing/lisp/test-org-src.el: * testing/lisp/test-org-attach.el: * testing/lisp/test-org-agenda.el: * testing/lisp/test-ob-java.el: Pass explicit filename to `require` so as not to rely on ".../testing" being in `load-path` during compilation. * lisp/org-num.el: Require` org`. * lisp/org-macs.el (org-eval-in-environment): Declare obsolete. (org-dlet, org-pushnew-to-end): New macros. * doc/Makefile (org.texi, orgguide.texi, %_letter.tex): Simplify quoting. * contrib/lisp/ob-sclang.el: Don't crash compilation when `sclang` is not available. * contrib/lisp/ob-clojure-literate.el: Don't crash compilation when `cider` is not available. * contrib/lisp/ob-arduino.el: Don't crash compilation when `arduino-mode` is not available. * .gitignore: Add files generated during `make packages/org`.
2021-02-23 20:47:29 +00:00
(require 'org-test "../testing/org-test")
(require 'org-agenda)
(eval-and-compile (require 'cl-lib))
2019-11-12 13:44:05 +00:00
;; General auxiliaries
(defun org-test-agenda--agenda-buffers ()
"Return agenda buffers in a list."
(cl-remove-if-not (lambda (x)
(with-current-buffer x
(eq major-mode 'org-agenda-mode)))
(buffer-list)))
(defun org-test-agenda--kill-all-agendas ()
"Kill all agenda buffers."
(mapc #'kill-buffer
(org-test-agenda--agenda-buffers)))
(defmacro org-test-agenda-with-agenda (text &rest body)
(declare (indent 1))
`(org-test-with-temp-text-in-file ,text
(let ((org-agenda-files `(,buffer-file-name)))
,@body
(org-test-agenda--kill-all-agendas))))
;; Test the Agenda
(ert-deftest test-org-agenda/empty ()
"Empty agenda."
(cl-assert (not org-agenda-sticky) nil "precondition violation")
(cl-assert (not (org-test-agenda--agenda-buffers))
nil "precondition violation")
(let ((org-agenda-span 'day)
org-agenda-files)
(org-agenda-list)
(set-buffer org-agenda-buffer-name)
(should (= 2 (count-lines (point-min) (point-max)))))
(org-test-agenda--kill-all-agendas))
(ert-deftest test-org-agenda/one-line ()
"One informative line in the agenda."
(cl-assert (not org-agenda-sticky) nil "precondition violation")
(cl-assert (not (org-test-agenda--agenda-buffers))
nil "precondition violation")
(let ((org-agenda-span 'day)
(org-agenda-files `(,(expand-file-name "examples/agenda-file.org"
org-test-dir))))
;; NOTE: Be aware that `org-agenda-list' may or may not display
;; past scheduled items depending whether the date is today
;; `org-today' or not.
(org-agenda-list nil "<2017-03-10 Fri>")
(set-buffer org-agenda-buffer-name)
(should (= 3 (count-lines (point-min) (point-max)))))
(org-test-agenda--kill-all-agendas))
(ert-deftest test-org-agenda/scheduled-non-todo ()
"One informative line in the agenda from scheduled non-todo-keyword-item."
(cl-assert (not org-agenda-sticky) nil "precondition violation")
(cl-assert (not (org-test-agenda--agenda-buffers))
nil "precondition violation")
(dolist (org-element-use-cache '(t nil))
(let ((org-agenda-span 'day)
(org-agenda-files `(,(expand-file-name "examples/agenda-file.org"
org-test-dir))))
;; NOTE: Be aware that `org-agenda-list' may or may not display
;; past scheduled items depending whether the date is today
;; `org-today' or not.
(org-agenda-list nil "<2017-07-19 Wed>")
(set-buffer org-agenda-buffer-name)
(should
(progn (goto-line 3)
(looking-at " *agenda-file:Scheduled: *test agenda"))))
(org-test-agenda--kill-all-agendas)))
(ert-deftest test-org-agenda/non-scheduled-re-matces ()
"Make sure that scheduled-looking elements do not appear in agenda.
See https://list.orgmode.org/20220101200103.GB29829@itccanarias.org/T/#t."
(cl-assert (not org-agenda-sticky) nil "precondition violation")
(cl-assert (not (org-test-agenda--agenda-buffers))
nil "precondition violation")
(let ((org-agenda-span 'day)
(org-agenda-files `(,(expand-file-name "examples/agenda-file.org"
org-test-dir))))
;; NOTE: Be aware that `org-agenda-list' may or may not display
;; past scheduled items depending whether the date is today
;; `org-today' or not.
(org-agenda-list nil "<2022-01-03 Mon>")
(set-buffer org-agenda-buffer-name)
(should (= 2 (count-lines (point-min) (point-max)))))
(org-test-agenda--kill-all-agendas))
(ert-deftest test-org-agenda/org-search-view ()
"Test `org-search-view' specifications."
(cl-assert (not org-agenda-sticky) nil "precondition violation")
(cl-assert (not (org-test-agenda--agenda-buffers))
nil "precondition violation")
;; Search a string.
(let ((org-agenda-files `(,(expand-file-name "examples/agenda-search.org"
org-test-dir))))
(org-search-view nil "foo")
(set-buffer org-agenda-buffer-name)
(should (= 4 (count-lines (point-min) (point-max)))))
;; Search past inlinetask.
(let ((org-agenda-files `(,(expand-file-name "examples/agenda-search.org"
org-test-dir))))
(org-search-view nil "bar")
(set-buffer org-agenda-buffer-name)
(should (= 3 (count-lines (point-min) (point-max)))))
;; Search inside inlinetask.
(let ((org-agenda-files `(,(expand-file-name "examples/agenda-search.org"
org-test-dir))))
(org-search-view nil "text inside inlinetask")
(set-buffer org-agenda-buffer-name)
(should (= 3 (count-lines (point-min) (point-max)))))
(org-test-agenda--kill-all-agendas))
(ert-deftest test-org-agenda/property-timestamp ()
"Match timestamps inside property drawer.
See https://list.orgmode.org/06d301d83d9e$f8b44340$ea1cc9c0$@tomdavey.com"
(cl-assert (not org-agenda-sticky) nil "precondition violation")
(cl-assert (not (org-test-agenda--agenda-buffers))
nil "precondition violation")
(let ((org-agenda-span 'day)
(org-agenda-files `(,(expand-file-name "examples/agenda-file.org"
org-test-dir))))
;; NOTE: Be aware that `org-agenda-list' may or may not display
;; past scheduled items depending whether the date is today
;; `org-today' or not.
(org-agenda-list nil "<2022-03-22 Tue>")
(set-buffer org-agenda-buffer-name)
(should (= 3 (count-lines (point-min) (point-max))))
;; NOTE: Be aware that `org-agenda-list' may or may not display
;; past scheduled items depending whether the date is today
;; `org-today' or not.
(org-agenda-list nil "<2022-03-25 Fri>")
(set-buffer org-agenda-buffer-name)
(should (= 3 (count-lines (point-min) (point-max)))))
(org-test-agenda--kill-all-agendas))
(ert-deftest test-org-agenda/set-priority ()
"One informative line in the agenda. Check that org-agenda-priority updates the agenda."
(cl-assert (not org-agenda-sticky) nil "precondition violation")
(cl-assert (not (org-test-agenda--agenda-buffers))
nil "precondition violation")
(let ((org-agenda-span 'day)
(org-agenda-files `(,(expand-file-name "examples/agenda-file.org"
org-test-dir))))
;; NOTE: Be aware that `org-agenda-list' may or may not display
;; past scheduled items depending whether the date is today
;; `org-today' or not.
(org-agenda-list nil "<2017-07-19 Wed>")
(set-buffer org-agenda-buffer-name)
(should
(progn (goto-line 3)
(org-agenda-priority ?B)
(looking-at-p " *agenda-file:Scheduled: *\\[#B\\] test agenda"))))
(org-test-agenda--kill-all-agendas))
(ert-deftest test-org-agenda/sticky-agenda-name ()
"Agenda buffer name after having created one sticky agenda buffer."
(cl-assert (not org-agenda-sticky) nil "precondition violation")
(cl-assert (not (org-test-agenda--agenda-buffers))
nil "precondition violation")
(let ((org-agenda-span 'day)
(buf (get-buffer org-agenda-buffer-name))
org-agenda-files)
(when buf (kill-buffer buf))
(dolist (fn '(org-agenda-list org-todo-list))
(org-test-with-temp-text "<2017-03-17 Fri>"
(org-follow-timestamp-link)) ;creates a sticky agenda
(org-test-agenda--kill-all-agendas)
(funcall fn)
(should (= 1 (length (org-test-agenda--agenda-buffers))))
(should (string= "*Org Agenda*"
(buffer-name (car (org-test-agenda--agenda-buffers)))))))
(org-test-agenda--kill-all-agendas))
(ert-deftest test-org-agenda/sticky-agenda-name-after-reload ()
"Agenda buffer name of sticky agenda after reload."
(cl-assert (not org-agenda-sticky) nil "precondition violation")
(cl-assert (not (org-test-agenda--agenda-buffers))
nil "precondition violation")
(org-toggle-sticky-agenda)
(let (org-agenda-files)
(org-agenda-list)
(let* ((agenda-buffer-name
(progn
(cl-assert (= 1 (length (org-test-agenda--agenda-buffers))))
(buffer-name (car (org-test-agenda--agenda-buffers))))))
(set-buffer agenda-buffer-name)
(org-agenda-redo)
(should (= 1 (length (org-test-agenda--agenda-buffers))))
(should (string= agenda-buffer-name
(buffer-name (car (org-test-agenda--agenda-buffers)))))))
(org-toggle-sticky-agenda)
(org-test-agenda--kill-all-agendas))
(ert-deftest test-org-agenda/sticky-agenda-filter-preset ()
"Update sticky agenda buffers properly with preset of filters."
(unless org-agenda-sticky
(org-toggle-sticky-agenda))
(org-test-agenda-with-agenda "* TODO Foo"
(org-set-property "CATEGORY" "foo")
(let ((org-agenda-custom-commands
'(("f" "foo: multi-command"
((tags-todo "+CATEGORY=\"foo\"")
(alltodo ""))
((org-agenda-category-filter-preset '("+foo"))))
("b" "bar: multi-command"
((tags-todo "+CATEGORY=\"bar\"")
(alltodo ""))
((org-agenda-category-filter-preset '("+bar"))))
("f1" "foo: single-command"
tags-todo "+CATEGORY=\"foo\""
((org-agenda-category-filter-preset '("+foo"))))
("b1" "bar: single-command"
tags-todo "+CATEGORY=\"bar\""
((org-agenda-category-filter-preset '("+bar"))))
("f2" "foo: single-command"
alltodo "" ((org-agenda-category-filter-preset '("+foo"))))
("b2" "bar: single-command"
alltodo "" ((org-agenda-category-filter-preset '("+bar")))))))
(org-agenda nil "f")
(org-agenda nil "b")
(set-buffer "*Org Agenda(f)*")
(org-agenda-redo)
(goto-char (point-min))
(should (not (invisible-p (1- (search-forward "TODO Foo")))))
(org-test-agenda--kill-all-agendas)
(org-agenda nil "f1")
(org-agenda nil "b1")
(set-buffer "*Org Agenda(f1:+CATEGORY=\"foo\")*")
(org-agenda-redo)
(goto-char (point-min))
(should (not (invisible-p (1- (search-forward "TODO Foo")))))
(org-test-agenda--kill-all-agendas)
(org-agenda nil "f2")
(org-agenda nil "b2")
(set-buffer "*Org Agenda(f2)*")
(org-agenda-redo)
(goto-char (point-min))
(should (not (invisible-p (1- (search-forward "TODO Foo")))))))
(org-toggle-sticky-agenda))
(ert-deftest test-org-agenda/goto-date ()
"Test `org-agenda-goto-date'."
(unwind-protect
(should
(equal
(time-to-days (org-time-string-to-time "2019-12-30"))
(let ((org-agenda-files nil))
(org-agenda-list nil nil 'day)
(org-agenda-goto-date "2019-12-30")
(get-text-property (point) 'day))))
(org-test-agenda--kill-all-agendas)))
(ert-deftest test-org-agenda/file-restriction ()
"Test file restriction for org agenda."
(org-test-with-temp-text-in-file "* TODO Foo"
(org-agenda-set-restriction-lock t)
(org-agenda nil "t")
(should (search-forward "Foo"))
(should (org-agenda-files))
(should-not (org-agenda-files t))
(org-agenda-remove-restriction-lock)
(goto-char (point-min))
(should-not (search-forward "Foo" nil t))
(should-not (org-agenda-files)))
(org-test-with-temp-text-in-file "* TODO Bar"
(org-agenda nil "t" 'buffer)
(should (search-forward "Bar"))
(should (org-agenda-files))
(should-not (org-agenda-files t))
(org-agenda-remove-restriction-lock)
(goto-char (point-min))
(should-not (search-forward "Bar" nil t))
(should-not (org-agenda-files)))
(org-test-with-temp-text-in-file "* TODO Bar"
(org-agenda nil "t" 'buffer)
(org-agenda nil "t")
(should-not (search-forward "Bar" nil t))
(should-not (org-agenda-files)))
(org-test-agenda--kill-all-agendas))
;; agenda redo
(require 'face-remap)
(ert-deftest test-org-agenda/rescale ()
"Text scale survives `org-agenda-redo'."
(org-test-agenda--kill-all-agendas)
(unwind-protect
(let ((org-agenda-span 'day)
org-agenda-files)
(org-agenda-list)
(set-buffer org-agenda-buffer-name)
(text-scale-mode)
(text-scale-set 11)
(cl-assert (and (boundp text-scale-mode) text-scale-mode))
(org-agenda-redo)
(should text-scale-mode)
(should (= 11 text-scale-mode-amount)))
(org-test-agenda--kill-all-agendas)))
(ert-deftest test-org-agenda/redo-setting ()
"Command settings survives `org-agenda-redo'."
(org-test-agenda--kill-all-agendas)
(let ((org-agenda-custom-commands
'(("t" "TODOs" alltodo ""
((org-agenda-overriding-header "Test"))))))
(org-agenda nil "t")
(org-agenda-redo)
(org-agenda-redo)
(goto-char (point-min))
(should (looking-at-p "Test")))
(org-test-agenda--kill-all-agendas))
(ert-deftest test-org-agenda/diary-inclusion ()
"Diary inclusion happens."
(org-test-agenda--kill-all-agendas)
(let ((diary-file (expand-file-name "examples/diary-file" org-test-dir))
(org-agenda-files `(,(expand-file-name "examples/agenda-file.org"
org-test-dir)))
(diary-date-forms '((month "[-/]" day "[^-/0-9]")
(year "[-/]" month "[-/]" day "[^0-9]")
(monthname " *" day "[^-0-9]")
(year " *" monthname " *" day "[^0-9]")
(dayname "\\W")))
(org-agenda-span 'day)
(org-agenda-include-diary t))
;; NOTE: Be aware that `org-agenda-list' may or may not display
;; past scheduled items depending whether the date is today
;; `org-today' or not.
(org-agenda-list nil "<2019-01-08>")
(should (search-forward "f0bcf0cd8bad93c1451bb6e1b2aaedef5cce7cbb" nil t))
(org-test-agenda--kill-all-agendas)))
;; agenda bulk actions
(ert-deftest test-org-agenda/bulk ()
"Bulk actions are applied to marked items."
(org-test-agenda-with-agenda "* TODO a\n* TODO b"
(org-todo-list)
(org-agenda-bulk-mark-all)
(cl-letf (((symbol-function 'read-char-exclusive)
(lambda () ?t))
((symbol-function 'completing-read)
testing: Make all files use `lexical-binding` Mainly, add the corresponding cookie, but also add various `require`s so that the compiler knows which vars should be trated as dynbound. This does not fix all the warnings, but does try to eliminate all those about "unused" variables. For the variables truly unused, the patch usually adds an underscore to their name to silence the warning. Some of the fixes affect files which already used `lexical-binding`. Not sure why the test worked before: maybe because the tests were run without compiling them first (which could cause some of the missing `require`d packages to be autoloaded before we got to the problematic code, thus hiding the problem)? I found some suspicious code, for which I added FIXMEs. There are also a few changes to the main files. * lisp/org-protocol.el (org-protocol-check-filename-for-protocol): Don't call `server-edit` if it's not yet defined. [ Needed to get the tests to pass. ] * lisp/ob-core.el (org-babel-temporary-directory) (org-babel-temporary-stable-directory): Always define (and use nil if we don't want to create a directory for it). Simplify the code based on the fact that (defvar V E) only evaluates E if V is not yet `boundp`. (org-babel-temp-file, org-babel-temp-stable-file) (org-babel-remove-temporary-directory) (org-babel-remove-temporary-stable-directory): Adjust accordingly. * lisp/org.el (org-log-beginning): Add FIXME. * testing/org-test.el: Require `org` and `org-id`. (org-id-locations-file): Don't `defconst` it. (org-test-at-id, org-test-in-example-file, org-test-at-marker) (org-test-with-temp-text, org-test-with-temp-text-in-file): Move edebug specs into `declare` (and simplify them). (org-test-with-tramp-remote-dir--worker): Declare dynbound tramp vars. (org--compile-when): Fix quoting of `exp`. (org-test-load): Tweak regexps. * testing/org-batch-test-init.el: Tweak regexp, remove dead code and add a FIXME about it. * testing/lisp/test-ox.el: Require `ox` instead of erroring out if it's not already loaded. Also require `org-inlinetask`. (org-test-with-parsed-data): Silence warnings when `info` is not used. (test-org-export/bind-keyword): Add FIXME. * testing/lisp/test-ox-publish.el: Require `org-test` and `ox-publish`. (test-org-publish/resolve-external-link): Expose lambdas to the compiler. Remove unused var `ids`. (test-org-publish/get-project-from-filename): Remove unused var `file`. * testing/lisp/test-org.el: Require `org-macs`, `org`, `org-inlinetask`, `org-refile`, and `org-agenda`. (test-org/org-read-date): Declare `org-time-was-given` as dynbound. (test-org/set-regexps-and-options): Add FIXME. * testing/lisp/test-org-timer.el: Require `org-timer`. * testing/lisp/test-org-table.el: Require `ox`. * testing/lisp/test-org-protocol.el: Require `org-protocol` instead of erroring out if it's not already loaded. Also require `capture`, and add missing `provide` statement. * testing/lisp/test-org-pcomplete.el: Require `org`. * testing/lisp/test-org-list.el: Require `org-list` and `org`. * testing/lisp/test-org-lint.el: Require `org-footnote` and `org-lint`. * testing/lisp/test-org-footnote.el: Require `org-footnote`. * testing/lisp/test-org-element.el: Require `org-element` instead of erroring out if it's not already loaded. Also require `org` and `org-inlinetask`. * testing/lisp/test-org-duration.el: Require `org-duration`. * testing/lisp/test-org-datetree.el: Require `org-datetree`. * testing/lisp/test-org-colview.el: Require `org-colview`, `org-duration`, and `org-inlinetask`. * testing/lisp/test-org-clock.el: Require `org-duration` and `org-clock`. * testing/lisp/test-org-archive.el: Require `org-archive`. * testing/lisp/test-org-agenda.el (test-org-agenda/bulk-custom-arg-func): Add FIXME. * testing/lisp/test-ol.el: Require `ol` and `org-id`. (test-org-link/store-link): Declare `org-store-link-props` and add FIXME. * testing/lisp/test-oc.el (test-org-cite/export-capability): Add FIXME. * testing/lisp/test-ob.el: Require `ob-core`, `org-src`, `ob-ref`, and `org-table`. (test-ob/eval-header-argument): Rename `foo` to `test-ob--foo` and declare it as dynbound. (test-ob/blocks-with-spaces, test-ob/specific-colnames): Add FIXME. (test-ob/noweb-expansions-in-cache): Declare `noweb-expansions-in-cache-var` as dynbound. * testing/lisp/test-ob-tangle.el: Require `org` and `ob-tangle`. * testing/lisp/test-ob-shell.el: * testing/lisp/test-ob-python.el: Require `ob-core`. * testing/lisp/test-ob-lob.el: Require `ob-lob`. (temporary-value-for-test): Declare as dynbound. * testing/lisp/test-ob-plantuml.el: Require `ob-plantuml` instead of erroring out if it's not already loaded. * testing/lisp/test-ob-lilypond.el: Require `ob-lilypond` instead of erroring out if it's not already loaded. Use `with-current-buffer`. * testing/lisp/test-ob-julia.el: Require `ob-core`. * testing/lisp/test-ob-java.el (org-babel-temporary-directory): Remove dead code now that `org-babel-temporary-directory` is always bound. * testing/lisp/test-ob-exp.el: Require `ob-exp`, `org-src`, and `org-test`. (ob-exp/evaluate-all-executables-in-order): Declare `*evaluation-collector*` as dynbound. * testing/lisp/test-ob-emacs-lisp.el (ob-emacs-lisp/dynamic-lexical-edit) (ob-emacs-lisp/dynamic-lexical-execute): Rename dynbound var to `ob-emacs--x` and declare it as such. * testing/lisp/test-ob-R.el: Require `ob-core`. (ess-ask-for-ess-directory, ess-history-file): Declare vars.
2022-09-14 21:21:37 +00:00
(lambda (&rest _rest) "DONE")))
(org-agenda-bulk-action))
(org-agenda-previous-item 99)
(should (looking-at ".*DONE a"))
(org-agenda-next-item 1)
(should (looking-at ".*DONE b"))))
(ert-deftest test-org-agenda/bulk-custom ()
"Custom bulk actions are applied to all marked items."
(org-test-agenda-with-agenda "* TODO a\n* TODO b"
(org-todo-list)
(org-agenda-bulk-mark-all)
;; Mock read functions
(let* ((f-call-cnt 0)
(org-agenda-bulk-custom-functions
`((?P ,(lambda () (setq f-call-cnt (1+ f-call-cnt)))))))
(cl-letf* (((symbol-function 'read-char-exclusive)
(lambda () ?P)))
(org-agenda-bulk-action)
(should (= f-call-cnt 2))))))
(ert-deftest test-org-agenda/bulk-custom-arg-func ()
"Argument collection functions can be specified for custom bulk
functions."
(org-test-agenda-with-agenda "* TODO a\n* TODO b"
(org-todo-list)
(org-agenda-bulk-mark-all)
(let* ((f-called-cnt 0)
(arg-f-call-cnt 0)
(f-called-args nil)
(org-agenda-bulk-custom-functions
`((?P
;; Custom bulk function
,(lambda (&rest args)
(message "test")
(setq f-called-cnt (1+ f-called-cnt)
f-called-args args))
;; Argument collection function
,(lambda ()
(setq arg-f-call-cnt (1+ arg-f-call-cnt))
'(1 2 3))))))
(cl-letf (((symbol-function 'read-char-exclusive)
(lambda () ?P)))
(org-agenda-bulk-action))
(should (= f-called-cnt 2))
(should (= arg-f-call-cnt 1))
(should (equal f-called-args '(1 2 3))))))
(provide 'test-org-agenda)
;;; test-org-agenda.el ends here