;;; test-gallery-widget.el --- ERT tests for gallery-widget.el -*- lexical-binding: t; -*- ;;; Commentary: ;; Tests for the svg.el proof-of-concept renderer in docs/prototypes/. ;; gallery-widget.el reads the generated gallery-tokens.el (same source of truth as ;; the web gallery and the waybar CSS) and renders gallery widgets as SVG. ;; These tests exercise the REAL module (loaded by path, not a copy): ;; token resolution, needle-angle math (normal/boundary/error), and the ;; rendered SVG document's structure. ;; ;; Run from repo root: ;; make test-elisp ;; (or emacs --batch -l ert -l tests/gallery-widgets/test-gallery-widget.el \ ;; -f ert-run-tests-batch-and-exit) ;;; Code: (require 'ert) (require 'cl-lib) (defvar test-gallery-widget--root (expand-file-name "../.." (file-name-directory (or load-file-name buffer-file-name))) "Repo root, derived from this test file's location.") (load (expand-file-name "docs/prototypes/gallery-widget.el" test-gallery-widget--root)) ;;; --- token access --- (ert-deftest gallery-widget-token-resolves-hex () "Known tokens resolve to hex color strings from the generated alist." (should (string-match-p "\\`#[0-9a-f]\\{6\\}\\'" (gallery-widget-token 'gold))) (should (string-match-p "\\`#[0-9a-f]\\{6\\}\\'" (gallery-widget-token 'glow-hi))) (should (string-match-p "\\`#[0-9a-f]\\{6\\}\\'" (gallery-widget-token 'wash)))) (ert-deftest gallery-widget-token-missing-errors () "An unknown token name signals an error rather than returning nil." (should-error (gallery-widget-token 'no-such-token))) ;;; --- needle angle math --- (ert-deftest gallery-widget-needle-angle-normal () "0..100 maps linearly onto -60..+60 degrees." (should (= (gallery-widget--needle-angle 0) -60.0)) (should (= (gallery-widget--needle-angle 50) 0.0)) (should (= (gallery-widget--needle-angle 100) 60.0))) (ert-deftest gallery-widget-needle-angle-boundary-clamps () "Out-of-range values clamp to the dial's ends instead of overswinging." (should (= (gallery-widget--needle-angle -5) -60.0)) (should (= (gallery-widget--needle-angle 150) 60.0))) (ert-deftest gallery-widget-needle-angle-error-non-number () "A non-numeric value signals an error." (should-error (gallery-widget--needle-angle "fifty")) (should-error (gallery-widget--needle-angle nil))) ;;; --- rendered SVG structure --- (defun test-gallery-widget--svg-string (value) "Render the needle gauge at VALUE and return its XML string." (gallery-widget-svg-string (gallery-widget-needle-gauge value))) (ert-deftest gallery-widget-gauge-renders-svg-document () "The gauge renders to a parseable SVG document." (let ((xml (test-gallery-widget--svg-string 42))) (should (string-match-p "\\`]*stroke=\"%s\"" (gallery-widget-token 'wash)) xml)) ;; exactly three ticks (should (= 3 (cl-count-if (lambda (_) t) (split-string xml "class=\"tick\"" t) :start 1))) ;; needle + hub in the amber tokens (should (string-match-p (format "class=\"needle\"[^>]*stroke=\"%s\"" (gallery-widget-token 'gold-hi)) xml)) ;; hub is a half-dome sitting on the dial's bottom edge, like the web card (should (string-match-p (format "class=\"hub\"[^>]*fill=\"%s\"" (gallery-widget-token 'gold)) xml)) (should (string-match-p "class=\"hub\"[^>]*d=\"M 44 48 A 4 4 0 0 1 52 48 Z\"" xml)) ;; value readout (should (string-match-p ">42%<" xml)))) (ert-deftest gallery-widget-gauge-has-glow-filter () "The needle glow is a real SVG blur filter, not a dropped effect." (let ((xml (test-gallery-widget--svg-string 42))) (should (string-match-p "feGaussianBlur" xml)) (should (string-match-p "filter=\"url(#" xml)))) (ert-deftest gallery-widget-gauge-needle-tracks-value () "The needle endpoint lands where the angle math says: left at 0, up at 50, right at 100." ;; value 50 -> vertical: x2 = pivot x (48), y2 = 48 - 40 = 8 (let ((xml (test-gallery-widget--svg-string 50))) (should (string-match-p "class=\"needle\"[^>]*x2=\"48.0+\"" xml)) (should (string-match-p "class=\"needle\"[^>]*y2=\"8.0+\"" xml))) ;; value 100 -> +60 deg: x2 = 48 + 40*sin60 ~ 82.64 (should (string-match-p "x2=\"82.6" (test-gallery-widget--svg-string 100))) ;; value 0 -> -60 deg: x2 = 48 - 40*sin60 ~ 13.36 (should (string-match-p "x2=\"13.3" (test-gallery-widget--svg-string 0)))) (ert-deftest gallery-widget-gauge-integer-percent-in-readout () "The readout shows a rounded integer percent, matching the web card." (should (string-match-p ">67%<" (test-gallery-widget--svg-string 66.6)))) (provide 'test-gallery-widget) ;;; test-gallery-widget.el ends here