diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test-calendar-sync--deferred-start.el | 43 | ||||
| -rw-r--r-- | tests/test-calibredb-epub-config.el | 11 | ||||
| -rw-r--r-- | tests/test-font-config--frame-lifecycle.el | 10 | ||||
| -rw-r--r-- | tests/test-font-config.el | 12 | ||||
| -rw-r--r-- | tests/test-nov-reading--palette.el | 92 | ||||
| -rw-r--r-- | tests/test-nov-reading--text-scale.el | 105 |
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 |
