summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-04-04 13:00:19 -0500
committerCraig Jennings <c@cjennings.net>2026-04-04 13:00:19 -0500
commit25b760d805e98ff3c0f0f9b29f75a108fb1dce10 (patch)
tree5ada9a76c1a5424043f721e2c3aeb2cd069eacbf
parent622ae39ad1e2544980cff73af8a5d5b2a64dacc8 (diff)
downloademacs-wttrin-25b760d805e98ff3c0f0f9b29f75a108fb1dce10.tar.gz
emacs-wttrin-25b760d805e98ff3c0f0f9b29f75a108fb1dce10.zip
fix: mode-line tooltip shows location in lowercase
wttr.in's %l format returns locations in lowercase (e.g., "new orleans, la") regardless of the query casing. Replace the API's location prefix with the user's original wttrin-favorite-location string at cache time so tooltips display what the user expects.
-rw-r--r--tests/test-wttrin--replace-response-location.el84
-rw-r--r--wttrin.el12
2 files changed, 95 insertions, 1 deletions
diff --git a/tests/test-wttrin--replace-response-location.el b/tests/test-wttrin--replace-response-location.el
new file mode 100644
index 0000000..3412ae9
--- /dev/null
+++ b/tests/test-wttrin--replace-response-location.el
@@ -0,0 +1,84 @@
+;;; test-wttrin--replace-response-location.el --- Tests for wttrin--replace-response-location -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2025-2026 Craig Jennings
+
+;;; Commentary:
+
+;; Unit tests for wttrin--replace-response-location function.
+;; Tests that the API's lowercase location prefix gets replaced with the
+;; user's original casing while preserving the weather data.
+
+;;; Code:
+
+(require 'ert)
+(require 'wttrin)
+(require 'testutil-wttrin)
+
+;;; Setup and Teardown
+
+(defun test-wttrin--replace-response-location-setup ()
+ "Setup for replace-response-location tests."
+ (testutil-wttrin-setup))
+
+(defun test-wttrin--replace-response-location-teardown ()
+ "Teardown for replace-response-location tests."
+ (testutil-wttrin-teardown))
+
+;;; Normal Cases
+
+(ert-deftest test-wttrin--replace-response-location-normal-replaces-lowercase ()
+ "API's lowercase location should be replaced with user's original casing."
+ (should (equal (wttrin--replace-response-location
+ "new orleans, la: ☀️ +72°F Clear"
+ "New Orleans, LA")
+ "New Orleans, LA: ☀️ +72°F Clear")))
+
+(ert-deftest test-wttrin--replace-response-location-normal-preserves-weather-data ()
+ "Everything after the colon should be identical to the original response."
+ (let* ((response "berlin: 🌧 +48°F Light rain")
+ (result (wttrin--replace-response-location response "Berlin")))
+ ;; Weather data portion should be untouched
+ (should (string-suffix-p ": 🌧 +48°F Light rain" result))))
+
+;;; Boundary Cases
+
+(ert-deftest test-wttrin--replace-response-location-boundary-already-correct ()
+ "When API casing already matches user's, the string should be unchanged."
+ (should (equal (wttrin--replace-response-location
+ "Paris: ☀️ +61°F Clear"
+ "Paris")
+ "Paris: ☀️ +61°F Clear")))
+
+(ert-deftest test-wttrin--replace-response-location-boundary-unicode ()
+ "Unicode location should be preserved correctly in the replacement."
+ (should (equal (wttrin--replace-response-location
+ "são paulo: 🌤 +77°F Partly cloudy"
+ "São Paulo")
+ "São Paulo: 🌤 +77°F Partly cloudy")))
+
+(ert-deftest test-wttrin--replace-response-location-boundary-no-colon ()
+ "Response with no colon should be returned unchanged."
+ (should (equal (wttrin--replace-response-location
+ "Unknown location"
+ "Paris")
+ "Unknown location")))
+
+;;; Integration: fetch populates cache with corrected casing
+
+(ert-deftest test-wttrin--mode-line-fetch-caches-user-location-casing ()
+ "After a successful fetch, the cached string should use the user's
+location casing, not the API's lowercase version."
+ (test-wttrin--replace-response-location-setup)
+ (unwind-protect
+ (let ((wttrin-favorite-location "New Orleans, LA")
+ (wttrin--mode-line-cache nil))
+ (testutil-wttrin-mock-http-response
+ "new orleans, la: ☀️ +72°F Clear"
+ (wttrin--mode-line-fetch-weather)
+ (should wttrin--mode-line-cache)
+ (let ((cached-string (cdr wttrin--mode-line-cache)))
+ (should (string-prefix-p "New Orleans, LA:" cached-string)))))
+ (test-wttrin--replace-response-location-teardown)))
+
+(provide 'test-wttrin--replace-response-location)
+;;; test-wttrin--replace-response-location.el ends here
diff --git a/wttrin.el b/wttrin.el
index c93aae2..972a2e8 100644
--- a/wttrin.el
+++ b/wttrin.el
@@ -507,6 +507,14 @@ This creates headroom to avoid frequent cleanups."
;;; Mode-line weather display
+(defun wttrin--replace-response-location (response location)
+ "Replace the API's location prefix in RESPONSE with LOCATION.
+The wttr.in API returns locations in lowercase. This substitutes the
+user's original casing so tooltips display what the user expects."
+ (if (string-match ":" response)
+ (concat location (substring response (match-beginning 0)))
+ response))
+
(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."
@@ -571,7 +579,9 @@ On failure with no cache, shows error placeholder."
(wttrin--debug-log "mode-line-fetch: Received data = %S" trimmed-data)
(if (wttrin--mode-line-valid-response-p trimmed-data)
(progn
- (setq wttrin--mode-line-cache (cons (float-time) trimmed-data))
+ (setq wttrin--mode-line-cache
+ (cons (float-time)
+ (wttrin--replace-response-location trimmed-data location)))
(wttrin--mode-line-update-display))
(wttrin--debug-log "mode-line-fetch: Invalid response, keeping previous display")))
;; Network error / nil data