diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-30 01:00:33 -0400 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-30 01:00:33 -0400 |
| commit | 6f43a260891deea175eeee83ec602f97a16c974e (patch) | |
| tree | 858f4fa16ceee6097eb34966aa4cb77035c77864 /tests | |
| parent | db903ea32b10ac2f8d10c7e718d81b68492225cc (diff) | |
| download | dotemacs-6f43a260891deea175eeee83ec602f97a16c974e.tar.gz dotemacs-6f43a260891deea175eeee83ec602f97a16c974e.zip | |
feat(nov-reading): persist font size, add per-palette structural faces
Font size now carries across books and sessions. The +/-/= keys write the text-scale offset to data/nov-reading-text-scale and the offset is restored when a book opens, so a size I set sticks instead of resetting to the base height on every reopen. The = key returns to the base height and persists that reset.
Each palette grows from a single bg/fg face into a bundle: :face plus optional :heading and :link. When a palette is active, its heading and link faces remap shr's h1-h6 and link faces buffer-local, so the EPUB hierarchy reads in the palette's accent. The remap stays buffer-local to the nov buffer, so HTML mail and eww keep the theme's normal shr colors.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test-nov-reading--palette.el | 42 | ||||
| -rw-r--r-- | tests/test-nov-reading--text-scale.el | 105 |
2 files changed, 142 insertions, 5 deletions
diff --git a/tests/test-nov-reading--palette.el b/tests/test-nov-reading--palette.el index 164ec75f4..b34ea2cac 100644 --- a/tests/test-nov-reading--palette.el +++ b/tests/test-nov-reading--palette.el @@ -13,28 +13,60 @@ (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 '(("sepia" . cj/nov-reading-sepia) - ("dark" . cj/nov-reading-dark)))) + "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 '(("sepia" . cj/nov-reading-sepia)))) + (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 '(("sepia" . cj/nov-reading-sepia)))) + (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 () 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 |
