aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test-calendar-sync--deferred-start.el43
-rw-r--r--tests/test-calibredb-epub-config.el11
-rw-r--r--tests/test-font-config--frame-lifecycle.el10
-rw-r--r--tests/test-font-config.el12
-rw-r--r--tests/test-nov-reading--palette.el92
-rw-r--r--tests/test-nov-reading--text-scale.el105
6 files changed, 257 insertions, 16 deletions
diff --git a/tests/test-calendar-sync--deferred-start.el b/tests/test-calendar-sync--deferred-start.el
new file mode 100644
index 000000000..a3a9c0198
--- /dev/null
+++ b/tests/test-calendar-sync--deferred-start.el
@@ -0,0 +1,43 @@
+;;; test-calendar-sync--deferred-start.el --- Deferred auto-start tests -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; calendar-sync arms its auto-sync on the first org-agenda use instead of at
+;; load, so a cold gpg-agent is not prompted for the authinfo passphrase at
+;; startup (the :secret-host feed URLs decrypt authinfo.gpg). These tests cover
+;; the one-shot helper: it starts sync once and removes itself, even when the
+;; start call errors.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'calendar-sync)
+
+;; org-agenda need not be loaded under `make test'; declare the hook special so
+;; the dynamic `let' bindings below shadow it cleanly.
+(defvar org-agenda-mode-hook)
+
+(ert-deftest test-calendar-sync-deferred-start-fires-once-and-unhooks ()
+ "Normal: the one-shot starts sync once and removes itself from the hook."
+ (let ((started 0)
+ (org-agenda-mode-hook (list #'calendar-sync--auto-start-on-first-agenda)))
+ (cl-letf (((symbol-function 'calendar-sync-start)
+ (lambda (&rest _) (setq started (1+ started)))))
+ (calendar-sync--auto-start-on-first-agenda))
+ (should (= started 1))
+ (should-not (member #'calendar-sync--auto-start-on-first-agenda
+ org-agenda-mode-hook))))
+
+(ert-deftest test-calendar-sync-deferred-start-unhooks-even-when-start-errors ()
+ "Error: a start failure still leaves the hook removed, so it cannot re-fire."
+ (let ((org-agenda-mode-hook (list #'calendar-sync--auto-start-on-first-agenda)))
+ (cl-letf (((symbol-function 'calendar-sync-start)
+ (lambda (&rest _) (error "boom"))))
+ (should-error (calendar-sync--auto-start-on-first-agenda)))
+ (should-not (member #'calendar-sync--auto-start-on-first-agenda
+ org-agenda-mode-hook))))
+
+(provide 'test-calendar-sync--deferred-start)
+;;; test-calendar-sync--deferred-start.el ends here
diff --git a/tests/test-calibredb-epub-config.el b/tests/test-calibredb-epub-config.el
index cb3a9ba74..71581d4c9 100644
--- a/tests/test-calibredb-epub-config.el
+++ b/tests/test-calibredb-epub-config.el
@@ -173,12 +173,13 @@ re-render of the document."
(should (commandp #'cj/nov-narrow-text)))
(ert-deftest test-calibredb-epub-nov-width-commands-bound-in-nov-mode-map ()
- "Normal: +/= widen and -/_ narrow the text column in `nov-mode-map'."
+ "Normal: { } adjust the text column in `nov-mode-map' (+/-/= are font size)."
(skip-unless (and (require 'nov nil t) (boundp 'nov-mode-map)))
- (should (eq (keymap-lookup nov-mode-map "+") #'cj/nov-widen-text))
- (should (eq (keymap-lookup nov-mode-map "=") #'cj/nov-widen-text))
- (should (eq (keymap-lookup nov-mode-map "-") #'cj/nov-narrow-text))
- (should (eq (keymap-lookup nov-mode-map "_") #'cj/nov-narrow-text)))
+ (should (eq (keymap-lookup nov-mode-map "}") #'cj/nov-widen-text))
+ (should (eq (keymap-lookup nov-mode-map "{") #'cj/nov-narrow-text))
+ (should (eq (keymap-lookup nov-mode-map "+") #'cj/nov-reading-text-bigger))
+ (should (eq (keymap-lookup nov-mode-map "-") #'cj/nov-reading-text-smaller))
+ (should (eq (keymap-lookup nov-mode-map "=") #'cj/nov-reading-text-reset)))
;;; -------------------------- cj/nov-apply-preferences ------------------------
diff --git a/tests/test-font-config--frame-lifecycle.el b/tests/test-font-config--frame-lifecycle.el
index 826edbd69..8f338b996 100644
--- a/tests/test-font-config--frame-lifecycle.el
+++ b/tests/test-font-config--frame-lifecycle.el
@@ -2,7 +2,7 @@
;;; Commentary:
;; cj/apply-font-settings-to-frame, cj/cleanup-frame-list, and
-;; cj/maybe-install-all-the-icons-fonts were defined inside use-package
+;; cj/maybe-install-nerd-icons-fonts were defined inside use-package
;; :config / with-eval-after-load (unreachable under `make test'). Lifting
;; them to top level makes their branching unit-testable; env-gui-p and the
;; package side-effect calls are mocked at the boundary.
@@ -57,9 +57,9 @@
(let ((installed nil))
(cl-letf (((symbol-function 'env-gui-p) (lambda () t))
((symbol-function 'cj/font-installed-p) (lambda (_n) nil))
- ((symbol-function 'all-the-icons-install-fonts) (lambda (&rest _) (setq installed t)))
+ ((symbol-function 'nerd-icons-install-fonts) (lambda (&rest _) (setq installed t)))
((symbol-function 'remove-hook) #'ignore))
- (cj/maybe-install-all-the-icons-fonts))
+ (cj/maybe-install-nerd-icons-fonts))
(should installed)))
(ert-deftest test-font-maybe-install-icons-already-present-skips ()
@@ -67,8 +67,8 @@
(let ((installed nil))
(cl-letf (((symbol-function 'env-gui-p) (lambda () t))
((symbol-function 'cj/font-installed-p) (lambda (_n) t))
- ((symbol-function 'all-the-icons-install-fonts) (lambda (&rest _) (setq installed t))))
- (cj/maybe-install-all-the-icons-fonts))
+ ((symbol-function 'nerd-icons-install-fonts) (lambda (&rest _) (setq installed t))))
+ (cj/maybe-install-nerd-icons-fonts))
(should-not installed)))
(provide 'test-font-config--frame-lifecycle)
diff --git a/tests/test-font-config.el b/tests/test-font-config.el
index 8fada25e2..393a77584 100644
--- a/tests/test-font-config.el
+++ b/tests/test-font-config.el
@@ -5,9 +5,10 @@
;; font-config.el is mostly top-level font/package setup. These smoke tests
;; cover the logic that should stay correct regardless of which fonts are
;; installed: the install check, and the daemon-frame font applier (env-gui-p
-;; guard plus idempotency). The module :demand's fontaine and all-the-icons,
-;; so the tests skip when those packages are absent rather than failing on a
-;; bare checkout. GUI and font lookups are stubbed so the run stays headless.
+;; guard plus idempotency). The module :demand's fontaine and references
+;; nerd-icons, so the tests skip when those packages are absent rather than
+;; failing on a bare checkout. GUI and font lookups are stubbed so the run
+;; stays headless.
;;; Code:
@@ -21,9 +22,8 @@
(defconst test-font-config--available
(and (locate-library "fontaine")
- (locate-library "all-the-icons")
- (locate-library "all-the-icons-nerd-fonts"))
- "Non-nil when the packages font-config :demand's are loadable.")
+ (locate-library "nerd-icons"))
+ "Non-nil when the packages font-config needs are loadable.")
;;; cj/font-installed-p
diff --git a/tests/test-nov-reading--palette.el b/tests/test-nov-reading--palette.el
new file mode 100644
index 000000000..b34ea2cac
--- /dev/null
+++ b/tests/test-nov-reading--palette.el
@@ -0,0 +1,92 @@
+;;; test-nov-reading--palette.el --- nov reading-palette tests -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Pure-logic tests for the nov-mode reading-palette selector: name->face
+;; resolution and the cycle order (palettes, then the no-palette state, wrapping).
+;; The buffer-local face-remap application is exercised live, not here.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'nov-reading)
+
+(declare-function cj/nov--reading-palette-face "nov-reading" (name))
+(declare-function cj/nov--reading-palette-plist "nov-reading" (name))
+(declare-function cj/nov--next-reading-palette "nov-reading" (current names))
+(defvar cj/nov-reading-palettes)
+
+;; Each palette entry is a property list: :face supplies bg/fg, :heading and
+;; :link recolor shr's heading/link faces. Structural keys are optional.
+(defconst test-nov-reading--palettes
+ '(("sepia" :face cj/nov-reading-sepia
+ :heading cj/nov-reading-sepia-heading
+ :link cj/nov-reading-sepia-link)
+ ("dark" :face cj/nov-reading-dark))
+ "Bundle-shaped palette fixture: sepia carries structural faces, dark omits them.")
+
+;;; ----------------------- cj/nov--reading-palette-face -----------------------
+
+(ert-deftest test-nov-reading-palette-face-known ()
+ "Normal: a known palette name resolves to its :face."
+ (let ((cj/nov-reading-palettes test-nov-reading--palettes))
+ (should (eq (cj/nov--reading-palette-face "sepia") 'cj/nov-reading-sepia))
+ (should (eq (cj/nov--reading-palette-face "dark") 'cj/nov-reading-dark))))
+
+(ert-deftest test-nov-reading-palette-face-unknown ()
+ "Error: an unknown name resolves to nil."
+ (let ((cj/nov-reading-palettes test-nov-reading--palettes))
+ (should-not (cj/nov--reading-palette-face "nope"))))
+
+(ert-deftest test-nov-reading-palette-face-nil ()
+ "Boundary: a nil name resolves to nil."
+ (let ((cj/nov-reading-palettes test-nov-reading--palettes))
+ (should-not (cj/nov--reading-palette-face nil))))
+
+;;; ---------------------- cj/nov--reading-palette-plist -----------------------
+
+(ert-deftest test-nov-reading-palette-plist-structural-faces ()
+ "Normal: a palette's :heading and :link faces are retrievable from its plist."
+ (let ((cj/nov-reading-palettes test-nov-reading--palettes))
+ (should (eq (plist-get (cj/nov--reading-palette-plist "sepia") :heading)
+ 'cj/nov-reading-sepia-heading))
+ (should (eq (plist-get (cj/nov--reading-palette-plist "sepia") :link)
+ 'cj/nov-reading-sepia-link))))
+
+(ert-deftest test-nov-reading-palette-plist-omitted-structural ()
+ "Boundary: a palette that omits structural keys yields nil for them."
+ (let ((cj/nov-reading-palettes test-nov-reading--palettes))
+ (should (eq (plist-get (cj/nov--reading-palette-plist "dark") :face)
+ 'cj/nov-reading-dark))
+ (should-not (plist-get (cj/nov--reading-palette-plist "dark") :heading))
+ (should-not (plist-get (cj/nov--reading-palette-plist "dark") :link))))
+
+(ert-deftest test-nov-reading-palette-plist-unknown ()
+ "Error: an unknown palette name yields a nil plist."
+ (let ((cj/nov-reading-palettes test-nov-reading--palettes))
+ (should-not (cj/nov--reading-palette-plist "nope"))))
+
+;;; ----------------------- cj/nov--next-reading-palette -----------------------
+
+(ert-deftest test-nov-reading-next-palette-advances ()
+ "Normal: cycles to the next palette in order."
+ (should (equal (cj/nov--next-reading-palette "sepia" '("sepia" "dark" "light"))
+ "dark")))
+
+(ert-deftest test-nov-reading-next-palette-last-to-none ()
+ "Boundary: the last palette cycles to the no-palette state (nil)."
+ (should-not (cj/nov--next-reading-palette "light" '("sepia" "dark" "light"))))
+
+(ert-deftest test-nov-reading-next-palette-none-to-first ()
+ "Boundary: the no-palette state (nil) cycles to the first palette."
+ (should (equal (cj/nov--next-reading-palette nil '("sepia" "dark" "light"))
+ "sepia")))
+
+(ert-deftest test-nov-reading-next-palette-unknown-current-falls-to-first ()
+ "Error: an unknown current palette falls back to the first."
+ (should (equal (cj/nov--next-reading-palette "gone" '("sepia" "dark" "light"))
+ "sepia")))
+
+(provide 'test-nov-reading--palette)
+;;; test-nov-reading--palette.el ends here
diff --git a/tests/test-nov-reading--text-scale.el b/tests/test-nov-reading--text-scale.el
new file mode 100644
index 000000000..8c2fed8b4
--- /dev/null
+++ b/tests/test-nov-reading--text-scale.el
@@ -0,0 +1,105 @@
+;;; test-nov-reading--text-scale.el --- nov reading text-scale persistence tests -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Tests for the persisted global reading text-scale offset: parsing the stored
+;; value (pure) and the save/load round-trip through the data file. The live
+;; text-scale application in the +/-/= commands is exercised live, not here.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'nov-reading)
+
+(declare-function cj/nov-reading--parse-text-scale "nov-reading" (s))
+(declare-function cj/nov-reading--load-text-scale "nov-reading" ())
+(declare-function cj/nov-reading--save-text-scale "nov-reading" (amount))
+(defvar cj/nov-reading-text-scale-file)
+
+;;; --------------------- cj/nov-reading--parse-text-scale ----------------------
+
+(ert-deftest test-nov-reading-parse-text-scale-positive ()
+ "Normal: a positive integer string parses to that integer."
+ (should (= (cj/nov-reading--parse-text-scale "3") 3)))
+
+(ert-deftest test-nov-reading-parse-text-scale-negative ()
+ "Normal: a negative integer string parses to that integer."
+ (should (= (cj/nov-reading--parse-text-scale "-2") -2)))
+
+(ert-deftest test-nov-reading-parse-text-scale-trailing-newline ()
+ "Boundary: surrounding whitespace/newline is tolerated."
+ (should (= (cj/nov-reading--parse-text-scale "4\n") 4)))
+
+(ert-deftest test-nov-reading-parse-text-scale-zero ()
+ "Boundary: \"0\" parses to 0."
+ (should (= (cj/nov-reading--parse-text-scale "0") 0)))
+
+(ert-deftest test-nov-reading-parse-text-scale-nil ()
+ "Boundary: nil parses to 0."
+ (should (= (cj/nov-reading--parse-text-scale nil) 0)))
+
+(ert-deftest test-nov-reading-parse-text-scale-empty ()
+ "Boundary: an empty string parses to 0."
+ (should (= (cj/nov-reading--parse-text-scale "") 0)))
+
+(ert-deftest test-nov-reading-parse-text-scale-garbage ()
+ "Error: non-numeric content parses to 0."
+ (should (= (cj/nov-reading--parse-text-scale "garbage") 0)))
+
+(ert-deftest test-nov-reading-parse-text-scale-float-rejected ()
+ "Error: a non-integer numeric string parses to 0 (offsets are integers)."
+ (should (= (cj/nov-reading--parse-text-scale "3.5") 0)))
+
+;;; ------------------ cj/nov-reading--save/load round-trip ---------------------
+
+(ert-deftest test-nov-reading-save-load-roundtrip-positive ()
+ "Normal: a saved positive offset loads back unchanged."
+ (let ((cj/nov-reading-text-scale-file (make-temp-file "nov-scale-")))
+ (unwind-protect
+ (progn
+ (cj/nov-reading--save-text-scale 4)
+ (should (= (cj/nov-reading--load-text-scale) 4)))
+ (delete-file cj/nov-reading-text-scale-file))))
+
+(ert-deftest test-nov-reading-save-load-roundtrip-negative ()
+ "Normal: a saved negative offset loads back unchanged."
+ (let ((cj/nov-reading-text-scale-file (make-temp-file "nov-scale-")))
+ (unwind-protect
+ (progn
+ (cj/nov-reading--save-text-scale -3)
+ (should (= (cj/nov-reading--load-text-scale) -3)))
+ (delete-file cj/nov-reading-text-scale-file))))
+
+(ert-deftest test-nov-reading-save-load-roundtrip-zero ()
+ "Boundary: a saved 0 offset loads back as 0."
+ (let ((cj/nov-reading-text-scale-file (make-temp-file "nov-scale-")))
+ (unwind-protect
+ (progn
+ (cj/nov-reading--save-text-scale 0)
+ (should (= (cj/nov-reading--load-text-scale) 0)))
+ (delete-file cj/nov-reading-text-scale-file))))
+
+(ert-deftest test-nov-reading-load-missing-file-defaults-zero ()
+ "Boundary: loading when no file exists yet returns 0."
+ (let ((cj/nov-reading-text-scale-file
+ (expand-file-name "nov-scale-absent"
+ (make-temp-file "nov-scale-dir-" t))))
+ (unwind-protect
+ (should (= (cj/nov-reading--load-text-scale) 0))
+ (delete-directory (file-name-directory cj/nov-reading-text-scale-file) t))))
+
+(ert-deftest test-nov-reading-save-creates-missing-directory ()
+ "Boundary: save creates the data directory when it is absent."
+ (let* ((dir (make-temp-file "nov-scale-dir-" t))
+ (cj/nov-reading-text-scale-file
+ (expand-file-name "sub/nov-reading-text-scale" dir)))
+ (unwind-protect
+ (progn
+ (cj/nov-reading--save-text-scale 2)
+ (should (file-readable-p cj/nov-reading-text-scale-file))
+ (should (= (cj/nov-reading--load-text-scale) 2)))
+ (delete-directory dir t))))
+
+(provide 'test-nov-reading--text-scale)
+;;; test-nov-reading--text-scale.el ends here