diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/gallery-widgets/test-gallery-widget.el | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/tests/gallery-widgets/test-gallery-widget.el b/tests/gallery-widgets/test-gallery-widget.el new file mode 100644 index 0000000..ec484bb --- /dev/null +++ b/tests/gallery-widgets/test-gallery-widget.el @@ -0,0 +1,114 @@ +;;; 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 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 "\\`<svg" xml)) + (should (with-temp-buffer + (insert xml) + (libxml-parse-xml-region (point-min) (point-max)))))) + +(ert-deftest gallery-widget-gauge-has-expected-parts () + "Arc, three ticks, needle, hub, and value text are all present." + (let ((xml (test-gallery-widget--svg-string 42))) + ;; arc path stroked in the wash token + (should (string-match-p (format "path[^>]*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 |
