aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-28 04:06:12 -0400
committerCraig Jennings <c@cjennings.net>2026-06-28 04:06:12 -0400
commitce74e30562dfac3f599a94a45ac16c3c2319ab41 (patch)
tree0677f2538373bd87099a3c69b249b495689277f5 /tests
parent19e103fea2e55a3e3bc3a777b4c618e644b57760 (diff)
downloademacs-wttrin-ce74e30562dfac3f599a94a45ac16c3c2319ab41.tar.gz
emacs-wttrin-ce74e30562dfac3f599a94a45ac16c3c2319ab41.zip
fix: drop stale async weather responses that overwrite a newer query
wttrin-query reuses the single *wttr.in* buffer, so requesting Paris then Berlin and having Paris return last overwrote the Berlin buffer. Each query now stamps a monotonic request id on the buffer; the callback displays only when its captured id still matches, so a superseded response is ignored.
Diffstat (limited to 'tests')
-rw-r--r--tests/test-wttrin-query-request-id.el56
1 files changed, 56 insertions, 0 deletions
diff --git a/tests/test-wttrin-query-request-id.el b/tests/test-wttrin-query-request-id.el
new file mode 100644
index 0000000..cf3c371
--- /dev/null
+++ b/tests/test-wttrin-query-request-id.el
@@ -0,0 +1,56 @@
+;;; test-wttrin-query-request-id.el --- Stale async response guard -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2024-2026 Craig Jennings
+
+;;; Commentary:
+;; wttrin-query reuses the single *wttr.in* buffer, so an async response for an
+;; earlier query that completes after a later one must not overwrite the newer
+;; buffer. A per-buffer request id, captured in the callback closure, drops the
+;; stale response.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+(require 'wttrin)
+(require 'testutil-wttrin)
+
+(ert-deftest test-wttrin-query-normal-current-callback-displays ()
+ "Normal: a query's own callback (matching request id) displays its result."
+ (let ((cb nil) (displayed nil))
+ (unwind-protect
+ (cl-letf (((symbol-function 'wttrin--get-cached-or-fetch)
+ (lambda (_loc c) (setq cb c)))
+ ((symbol-function 'switch-to-buffer)
+ (lambda (buf &rest _) (set-buffer buf)))
+ ((symbol-function 'wttrin--display-weather)
+ (lambda (query &rest _) (setq displayed query))))
+ (wttrin-query "Paris")
+ (funcall cb "paris-data")
+ (should (equal displayed "Paris")))
+ (when (get-buffer "*wttr.in*") (kill-buffer "*wttr.in*")))))
+
+(ert-deftest test-wttrin-query-error-stale-callback-does-not-overwrite-newer ()
+ "Error: a slow response for an earlier query does not overwrite a newer query.
+Paris then Berlin share the *wttr.in* buffer; the Paris callback arriving after
+Berlin must be ignored."
+ (let ((callbacks nil) (displayed nil))
+ (unwind-protect
+ (cl-letf (((symbol-function 'wttrin--get-cached-or-fetch)
+ (lambda (_loc cb) (push cb callbacks)))
+ ((symbol-function 'switch-to-buffer)
+ (lambda (buf &rest _) (set-buffer buf)))
+ ((symbol-function 'wttrin--display-weather)
+ (lambda (query &rest _) (setq displayed query))))
+ (wttrin-query "Paris")
+ (wttrin-query "Berlin")
+ (let ((paris-cb (cadr callbacks)) ; first pushed
+ (berlin-cb (car callbacks))) ; last pushed
+ (funcall berlin-cb "berlin-data")
+ (should (equal displayed "Berlin"))
+ (funcall paris-cb "paris-data")
+ (should (equal displayed "Berlin"))))
+ (when (get-buffer "*wttr.in*") (kill-buffer "*wttr.in*")))))
+
+(provide 'test-wttrin-query-request-id)
+;;; test-wttrin-query-request-id.el ends here