summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-11 18:17:22 -0500
committerCraig Jennings <c@cjennings.net>2026-05-11 18:17:22 -0500
commite0e0ecdb86e3ae1772adcedb50e6c9caa210cf17 (patch)
tree41a16c890b1ffb588635266d45fc484beb85f9de /tests
parentfc94e5b7101f6677950c414c2822b451351ccc56 (diff)
downloaddotemacs-e0e0ecdb86e3ae1772adcedb50e6c9caa210cf17.tar.gz
dotemacs-e0e0ecdb86e3ae1772adcedb50e6c9caa210cf17.zip
test: close coverage gaps from the preceding batch
Untested paths surfaced while reviewing the preceding feature/fix commits: - calendar-sync: a test that `-L' precedes `-l' in the worker command (separate `member' checks wouldn't catch a swap), plus a `:slow' tag on the real-subprocess worker test so it stays out of the default `make test' run. - org-capture cache: a killed marker buffer invalidates the entry and the next resolution rescans without erroring on the stale marker, `cj/org-capture-clear-target-cache' actually empties the hash, and non-`file+headline' targets (`file', `file+olp', `file+function') fall through to the original `org-capture-set-target-location'. - lorem-optimum: `cj/lipsum-title' on an empty chain returns "", not an error. - calibredb-epub: a negative `cj/nov-margin-percent' is clamped up to 0 (text takes the full window width). - mu4e attachments: the default save directory comes from the part's `:target-dir' and falls back to `~/Downloads/', and asking for the attachment at point on a header line fails with a `user-error'.
Diffstat (limited to 'tests')
-rw-r--r--tests/test-calendar-sync-async-worker.el13
-rw-r--r--tests/test-calibredb-epub-config.el11
-rw-r--r--tests/test-lorem-optimum.el6
-rw-r--r--tests/test-mail-config-attachments.el25
-rw-r--r--tests/test-org-capture-config-target-cache.el48
5 files changed, 103 insertions, 0 deletions
diff --git a/tests/test-calendar-sync-async-worker.el b/tests/test-calendar-sync-async-worker.el
index 6701df85..3bf803ec 100644
--- a/tests/test-calendar-sync-async-worker.el
+++ b/tests/test-calendar-sync-async-worker.el
@@ -37,8 +37,21 @@
(string-match-p "'(\"me@example\\.test\")" arg)))
command))))
+(ert-deftest test-calendar-sync--worker-command-puts-L-before-l ()
+ "Order: `-L module-dir' must precede `-l calendar-sync.el' so the sibling
+load-path entry is in effect by the time the module load runs. Asserting both
+via `member' separately wouldn't catch a swap."
+ (let* ((calendar-sync--module-file "/tmp/calendar-sync.el")
+ (calendar-sync-past-months 2)
+ (calendar-sync-future-months 6)
+ (calendar-sync-user-emails '("me@example.test"))
+ (command (calendar-sync--worker-command "/tmp/input.ics" "/tmp/output.org")))
+ (should (< (cl-position "-L" command :test #'equal)
+ (cl-position "-l" command :test #'equal)))))
+
(ert-deftest test-calendar-sync--worker-command-loads-sibling-modules-without-init ()
"The worker command should load calendar-sync and sibling modules without init."
+ :tags '(:slow)
(let* ((calendar-sync--module-file
(expand-file-name "modules/calendar-sync.el" user-emacs-directory))
(command (append
diff --git a/tests/test-calibredb-epub-config.el b/tests/test-calibredb-epub-config.el
index 5b578b7d..53d2e78f 100644
--- a/tests/test-calibredb-epub-config.el
+++ b/tests/test-calibredb-epub-config.el
@@ -40,6 +40,17 @@
(lambda (&rest _) nil)))
(should (= 40 (cj/nov--text-width-for-window))))))
+(ert-deftest test-calibredb-epub-nov-text-width-clamps-negative-margin ()
+ "Boundary: a negative margin percent is clamped up to 0, so the text takes
+the full window width."
+ (let ((cj/nov-margin-percent -10)
+ (cj/nov-min-text-width 40))
+ (cl-letf (((symbol-function 'get-buffer-window)
+ (lambda (&rest _) 'window))
+ ((symbol-function 'window-body-width)
+ (lambda (_) 120)))
+ (should (= 120 (cj/nov--text-width-for-window))))))
+
(ert-deftest test-calibredb-epub-open-external-uses-zathura ()
"Normal: named Nov external-open command delegates to zathura."
(let (command)
diff --git a/tests/test-lorem-optimum.el b/tests/test-lorem-optimum.el
index 40bdc684..f928c972 100644
--- a/tests/test-lorem-optimum.el
+++ b/tests/test-lorem-optimum.el
@@ -247,5 +247,11 @@
(should (> (length result) 0))
(should (string-match-p "^[[:upper:]]" result)))))
+(ert-deftest test-title-generation-empty-chain-returns-empty-string ()
+ "Boundary: an empty Markov chain (`cj/markov-random-key' returns nil) yields
+an empty string, not an error."
+ (let ((cj/lipsum-chain (cj/markov-chain-create)))
+ (should (equal "" (cj/lipsum-title)))))
+
(provide 'test-lorem-optimum)
;;; test-lorem-optimum.el ends here
diff --git a/tests/test-mail-config-attachments.el b/tests/test-mail-config-attachments.el
index eee0ff70..fae50c9c 100644
--- a/tests/test-mail-config-attachments.el
+++ b/tests/test-mail-config-attachments.el
@@ -233,5 +233,30 @@
(should (eq (lookup-key cj/email-map (kbd "m"))
#'cj/mu4e-save-some-attachments)))
+(ert-deftest test-mail-config-attachments-default-directory-uses-target-dir ()
+ "Normal: the default save directory comes from the part's :target-dir."
+ (let ((parts (list (test-mail-config-attachment--part "a.pdf" 1))))
+ (should (equal (cj/mu4e--attachment-default-directory parts)
+ "/tmp/mail-target/"))))
+
+(ert-deftest test-mail-config-attachments-default-directory-falls-back-to-downloads ()
+ "Boundary: with no :target-dir hint, the default is ~/Downloads/."
+ (let ((parts (list (list :filename "a.pdf" :part-index 1 :attachment-like t))))
+ (should (equal (cj/mu4e--attachment-default-directory parts)
+ (file-name-as-directory (expand-file-name "~/Downloads/"))))))
+
+(ert-deftest test-mail-config-attachments-selection-entry-at-point-errors-off-row ()
+ "Error: asking for the attachment at point on a header line fails clearly."
+ (let* ((a (test-mail-config-attachment--part "a.pdf" 1))
+ (buffer (get-buffer-create "*test-mail-attachments*")))
+ (unwind-protect
+ (with-current-buffer buffer
+ (cj/mu4e-attachment-selection-mode)
+ (cj/mu4e--attachment-selection-setup (list a) "/downloads/")
+ (goto-char (point-min)) ; first line is the "Save attachments to:" header
+ (should-error (cj/mu4e--attachment-selection-entry-at-point)
+ :type 'user-error))
+ (kill-buffer buffer))))
+
(provide 'test-mail-config-attachments)
;;; test-mail-config-attachments.el ends here
diff --git a/tests/test-org-capture-config-target-cache.el b/tests/test-org-capture-config-target-cache.el
index 7b88975b..f127bfbc 100644
--- a/tests/test-org-capture-config-target-cache.el
+++ b/tests/test-org-capture-config-target-cache.el
@@ -85,5 +85,53 @@ The file-visiting buffer is killed after BODY returns."
(should (cj/org-capture--headline-marker-valid-p marker "Inbox")))))
(test-org-capture-target-cache--reset)))
+(ert-deftest test-org-capture-target-cache-recovers-after-buffer-killed ()
+ "Boundary: killing the marker's buffer invalidates the cache entry.
+The next capture rescans (and refreshes), without crashing on the stale marker."
+ (test-org-capture-target-cache--reset)
+ (unwind-protect
+ (test-org-capture-target-cache--with-temp-org-file
+ "* Inbox\n"
+ (let ((org-capture-plist `(:target (file+headline ,file "Inbox"))))
+ (org-capture-set-target-location)
+ (let* ((key (cj/org-capture--file-headline-cache-key file "Inbox"))
+ (marker (gethash key cj/org-capture--file-headline-target-cache)))
+ (kill-buffer (marker-buffer marker))
+ (should-not (cj/org-capture--headline-marker-valid-p marker "Inbox"))
+ ;; A second resolution must succeed without erroring on the stale marker.
+ (org-capture-set-target-location)
+ (let ((fresh (gethash key cj/org-capture--file-headline-target-cache)))
+ (should (cj/org-capture--headline-marker-valid-p fresh "Inbox"))))))
+ (test-org-capture-target-cache--reset)))
+
+(ert-deftest test-org-capture-target-cache-clear-empties-the-hash ()
+ "Normal: `cj/org-capture-clear-target-cache' actually empties the cache."
+ (test-org-capture-target-cache--reset)
+ (unwind-protect
+ (test-org-capture-target-cache--with-temp-org-file
+ "* Inbox\n"
+ (let ((org-capture-plist `(:target (file+headline ,file "Inbox"))))
+ (org-capture-set-target-location)
+ (should (= 1 (hash-table-count cj/org-capture--file-headline-target-cache)))
+ ;; Suppress the user-facing message during the test.
+ (cl-letf (((symbol-function 'message) (lambda (&rest _) nil)))
+ (cj/org-capture-clear-target-cache))
+ (should (= 0 (hash-table-count cj/org-capture--file-headline-target-cache)))))
+ (test-org-capture-target-cache--reset)))
+
+(ert-deftest test-org-capture-target-cache-falls-through-for-non-file+headline ()
+ "Boundary: targets that aren't `file+headline' (e.g. plain `file', `file+olp',
+`file+function') fall through to the original `org-capture-set-target-location'
+unchanged."
+ (test-org-capture-target-cache--reset)
+ (dolist (target '((file "/tmp/fall-through.org")
+ (file+olp "/tmp/fall-through.org" "Tasks" "Inbox")
+ (file+function "/tmp/fall-through.org" ignore)))
+ (let ((called-with nil))
+ (cj/org-capture--set-target-location-advice
+ (lambda (&optional received) (setq called-with (list :ran received)))
+ target)
+ (should (equal called-with (list :ran target))))))
+
(provide 'test-org-capture-config-target-cache)
;;; test-org-capture-config-target-cache.el ends here