aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/test-wttrin--mode-line-helpers.el128
-rw-r--r--wttrin.el72
2 files changed, 160 insertions, 40 deletions
diff --git a/tests/test-wttrin--mode-line-helpers.el b/tests/test-wttrin--mode-line-helpers.el
new file mode 100644
index 0000000..b4c6b4e
--- /dev/null
+++ b/tests/test-wttrin--mode-line-helpers.el
@@ -0,0 +1,128 @@
+;;; test-wttrin--mode-line-helpers.el --- Tests for mode-line helper functions -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2025 Craig Jennings
+
+;;; Commentary:
+
+;; Unit tests for wttrin--make-emoji-icon and wttrin--set-mode-line-string.
+;; These helpers extract the common mode-line icon creation and string
+;; assignment pattern used by placeholder, error, and display functions.
+
+;;; Code:
+
+(require 'ert)
+(require 'wttrin)
+(require 'testutil-wttrin)
+
+;;; Setup and Teardown
+
+(defun test-wttrin--mode-line-helpers-setup ()
+ "Setup for mode-line helper tests."
+ (testutil-wttrin-setup)
+ (setq wttrin-mode-line-string nil))
+
+(defun test-wttrin--mode-line-helpers-teardown ()
+ "Teardown for mode-line helper tests."
+ (testutil-wttrin-teardown)
+ (setq wttrin-mode-line-string nil))
+
+;;; --------------------------------------------------------------------------
+;;; wttrin--make-emoji-icon
+;;; --------------------------------------------------------------------------
+
+;;; Normal Cases
+
+(ert-deftest test-wttrin--make-emoji-icon-normal-without-font ()
+ "Without emoji font configured, should return the plain emoji string."
+ (let ((wttrin-mode-line-emoji-font nil))
+ (should (equal (wttrin--make-emoji-icon "☀") "☀"))))
+
+(ert-deftest test-wttrin--make-emoji-icon-normal-with-font ()
+ "With emoji font configured, should apply font family face property."
+ (let ((wttrin-mode-line-emoji-font "Noto Color Emoji"))
+ (let ((result (wttrin--make-emoji-icon "☀")))
+ (should (stringp result))
+ (let ((face (get-text-property 0 'face result)))
+ (should (equal (plist-get face :family) "Noto Color Emoji"))
+ (should (equal (plist-get face :height) 1.0))))))
+
+(ert-deftest test-wttrin--make-emoji-icon-normal-with-foreground ()
+ "Foreground color should be applied when specified."
+ (let ((wttrin-mode-line-emoji-font nil))
+ (let ((result (wttrin--make-emoji-icon "☀" "gray60")))
+ (let ((face (get-text-property 0 'face result)))
+ (should (equal (plist-get face :foreground) "gray60"))))))
+
+(ert-deftest test-wttrin--make-emoji-icon-normal-with-font-and-foreground ()
+ "Both font and foreground should be applied together."
+ (let ((wttrin-mode-line-emoji-font "Noto Color Emoji"))
+ (let ((result (wttrin--make-emoji-icon "⏳" "gray60")))
+ (let ((face (get-text-property 0 'face result)))
+ (should (equal (plist-get face :family) "Noto Color Emoji"))
+ (should (equal (plist-get face :foreground) "gray60"))))))
+
+;;; Boundary Cases
+
+(ert-deftest test-wttrin--make-emoji-icon-boundary-nil-foreground-no-color ()
+ "Nil foreground should not add any :foreground property when no font."
+ (let ((wttrin-mode-line-emoji-font nil))
+ (let ((result (wttrin--make-emoji-icon "☀" nil)))
+ ;; Without font or foreground, should be plain string
+ (should (equal result "☀")))))
+
+;;; --------------------------------------------------------------------------
+;;; wttrin--set-mode-line-string
+;;; --------------------------------------------------------------------------
+
+;;; Normal Cases
+
+(ert-deftest test-wttrin--set-mode-line-string-normal-sets-string ()
+ "Should set wttrin-mode-line-string to a non-nil propertized value."
+ (test-wttrin--mode-line-helpers-setup)
+ (unwind-protect
+ (progn
+ (wttrin--set-mode-line-string "X" "tooltip text")
+ (should wttrin-mode-line-string))
+ (test-wttrin--mode-line-helpers-teardown)))
+
+(ert-deftest test-wttrin--set-mode-line-string-normal-includes-icon ()
+ "The icon text should appear in the mode-line string."
+ (test-wttrin--mode-line-helpers-setup)
+ (unwind-protect
+ (progn
+ (wttrin--set-mode-line-string "⏳" "tip")
+ (should (string-match-p "⏳" (substring-no-properties wttrin-mode-line-string))))
+ (test-wttrin--mode-line-helpers-teardown)))
+
+(ert-deftest test-wttrin--set-mode-line-string-normal-has-tooltip ()
+ "The help-echo property should contain the tooltip text."
+ (test-wttrin--mode-line-helpers-setup)
+ (unwind-protect
+ (progn
+ (wttrin--set-mode-line-string "X" "Weather is sunny")
+ (should (equal (get-text-property 0 'help-echo wttrin-mode-line-string)
+ "Weather is sunny")))
+ (test-wttrin--mode-line-helpers-teardown)))
+
+(ert-deftest test-wttrin--set-mode-line-string-normal-has-keymap ()
+ "The local-map property should be the mode-line keymap."
+ (test-wttrin--mode-line-helpers-setup)
+ (unwind-protect
+ (progn
+ (wttrin--set-mode-line-string "X" "tip")
+ (should (eq (get-text-property 0 'local-map wttrin-mode-line-string)
+ wttrin--mode-line-map)))
+ (test-wttrin--mode-line-helpers-teardown)))
+
+(ert-deftest test-wttrin--set-mode-line-string-normal-has-mouse-face ()
+ "The mouse-face property should highlight on hover."
+ (test-wttrin--mode-line-helpers-setup)
+ (unwind-protect
+ (progn
+ (wttrin--set-mode-line-string "X" "tip")
+ (should (equal (get-text-property 0 'mouse-face wttrin-mode-line-string)
+ 'mode-line-highlight)))
+ (test-wttrin--mode-line-helpers-teardown)))
+
+(provide 'test-wttrin--mode-line-helpers)
+;;; test-wttrin--mode-line-helpers.el ends here
diff --git a/wttrin.el b/wttrin.el
index cae61af..94e0923 100644
--- a/wttrin.el
+++ b/wttrin.el
@@ -508,6 +508,27 @@ This creates headroom to avoid frequent cleanups."
;;; Mode-line weather display
+(defun wttrin--make-emoji-icon (emoji &optional foreground)
+ "Create EMOJI string with optional font face and FOREGROUND color.
+Uses `wttrin-mode-line-emoji-font' when configured."
+ (if wttrin-mode-line-emoji-font
+ (propertize emoji
+ 'face (list :family wttrin-mode-line-emoji-font
+ :height 1.0
+ :foreground foreground))
+ (if foreground
+ (propertize emoji 'face (list :foreground foreground))
+ emoji)))
+
+(defun wttrin--set-mode-line-string (icon tooltip)
+ "Set mode-line weather string to ICON with TOOLTIP and standard properties."
+ (setq wttrin-mode-line-string
+ (propertize (concat " " icon)
+ 'help-echo tooltip
+ 'mouse-face 'mode-line-highlight
+ 'local-map wttrin--mode-line-map))
+ (force-mode-line-update t))
+
(defun wttrin--mode-line-valid-response-p (weather-string)
"Return non-nil if WEATHER-STRING looks like a valid mode-line response.
Expected format: \"Location: emoji temp conditions\",
@@ -520,19 +541,11 @@ e.g., \"Paris: ☀️ +61°F Clear\"."
"Update placeholder to show fetch error state.
Keeps the hourglass icon but updates tooltip to explain the failure
and indicate when retry will occur."
- (let* ((icon (if wttrin-mode-line-emoji-font
- (propertize "⏳"
- 'face (list :family wttrin-mode-line-emoji-font
- :height 1.0))
- "⏳"))
- (retry-minutes (ceiling (/ wttrin-mode-line-refresh-interval 60.0))))
- (setq wttrin-mode-line-string
- (propertize (concat " " icon)
- 'help-echo (format "Weather fetch failed for %s — will retry in %d minutes"
- wttrin-favorite-location retry-minutes)
- 'mouse-face 'mode-line-highlight
- 'local-map wttrin--mode-line-map)))
- (force-mode-line-update t))
+ (let ((retry-minutes (ceiling (/ wttrin-mode-line-refresh-interval 60.0))))
+ (wttrin--set-mode-line-string
+ (wttrin--make-emoji-icon "⏳")
+ (format "Weather fetch failed for %s — will retry in %d minutes"
+ wttrin-favorite-location retry-minutes))))
(defun wttrin--mode-line-fetch-weather ()
"Fetch weather for favorite location and update mode-line display.
@@ -587,27 +600,15 @@ shows staleness info in tooltip."
(let* ((emoji (if (string-match ":\\s-*\\(.\\)" weather-string)
(match-string 1 weather-string)
"?"))
- (emoji-with-font
- (if wttrin-mode-line-emoji-font
- (propertize emoji
- 'face (list :family wttrin-mode-line-emoji-font
- :height 1.0
- :foreground (when stale-p "gray60")))
- (if stale-p
- (propertize emoji 'face '(:foreground "gray60"))
- emoji)))
(tooltip (if stale-p
(format "%s\nStale: updated %s — fetch failed, will retry"
weather-string age-str)
(format "%s\nUpdated %s" weather-string age-str))))
(wttrin--debug-log "mode-line-display: Extracted emoji = %S, stale = %s"
emoji stale-p)
- (setq wttrin-mode-line-string
- (propertize (concat " " emoji-with-font)
- 'help-echo tooltip
- 'mouse-face 'mode-line-highlight
- 'local-map wttrin--mode-line-map)))))
- (force-mode-line-update t))
+ (wttrin--set-mode-line-string
+ (wttrin--make-emoji-icon emoji (when stale-p "gray60"))
+ tooltip)))))
(defun wttrin-mode-line-click ()
"Handle left-click on mode-line weather widget.
@@ -626,18 +627,9 @@ Force-refresh cache and update tooltip without opening buffer."
(defun wttrin--mode-line-set-placeholder ()
"Set a placeholder icon in the mode-line while waiting for weather data."
- (let ((icon (if wttrin-mode-line-emoji-font
- (propertize "⏳"
- 'face (list :family wttrin-mode-line-emoji-font
- :height 1.0))
- "⏳")))
- (setq wttrin-mode-line-string
- (propertize (concat " " icon)
- 'help-echo (format "Fetching weather for %s..."
- wttrin-favorite-location)
- 'mouse-face 'mode-line-highlight
- 'local-map wttrin--mode-line-map)))
- (force-mode-line-update t))
+ (wttrin--set-mode-line-string
+ (wttrin--make-emoji-icon "⏳")
+ (format "Fetching weather for %s..." wttrin-favorite-location)))
(defvar wttrin--buffer-refresh-timer nil
"Timer object for proactive buffer cache refresh.")