aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test-wttrin-geolocation-sentinel.el212
-rw-r--r--tests/test-wttrin-location-history.el24
-rw-r--r--tests/test-wttrin-make-default.el5
-rw-r--r--tests/test-wttrin-requery.el9
-rw-r--r--tests/test-wttrin-set-location-from-geolocation.el29
5 files changed, 267 insertions, 12 deletions
diff --git a/tests/test-wttrin-geolocation-sentinel.el b/tests/test-wttrin-geolocation-sentinel.el
new file mode 100644
index 0000000..0536173
--- /dev/null
+++ b/tests/test-wttrin-geolocation-sentinel.el
@@ -0,0 +1,212 @@
+;;; test-wttrin-geolocation-sentinel.el --- Tests for the picker geolocation sentinel -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2024-2026 Craig Jennings
+
+;;; Commentary:
+;; Unit tests for the "Current location (detect)" picker sentinel: its presence
+;; and position in `wttrin--completion-candidates', the selection routing in
+;; `wttrin--query-selection' (literal vs detect-then-query), and the guard that
+;; keeps the sentinel out of location history.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+(require 'wttrin)
+(require 'wttrin-geolocation)
+(require 'testutil-wttrin)
+
+;;; wttrin--completion-candidates — sentinel presence and position
+
+(ert-deftest test-wttrin-geolocation-sentinel-normal-first-candidate ()
+ "Normal: the sentinel is the first completion candidate."
+ (testutil-wttrin-setup)
+ (unwind-protect
+ (let ((wttrin-favorite-location nil)
+ (wttrin-default-locations '("Honolulu, HI"))
+ (wttrin--location-history '("Tokyo")))
+ (should (equal wttrin--geolocation-sentinel
+ (car (wttrin--completion-candidates)))))
+ (testutil-wttrin-teardown)))
+
+(ert-deftest test-wttrin-geolocation-sentinel-normal-first-even-with-favorite ()
+ "Normal: the sentinel precedes a string favorite in the candidate list."
+ (testutil-wttrin-setup)
+ (unwind-protect
+ (let ((wttrin-favorite-location "New Orleans, LA")
+ (wttrin-default-locations '("Honolulu, HI"))
+ (wttrin--location-history nil))
+ (should (equal (list wttrin--geolocation-sentinel
+ "New Orleans, LA" "Honolulu, HI")
+ (wttrin--completion-candidates))))
+ (testutil-wttrin-teardown)))
+
+;;; wttrin--sort-completions — pin the sentinel first
+
+(ert-deftest test-wttrin-geolocation-sentinel-normal-sort-pins-first ()
+ "Normal: the sentinel is moved to the front, the rest keep their order.
+Sorting completion UIs (vertico, icomplete) call the metadata
+display-sort-function, so this is what keeps the sentinel pinned."
+ (should (equal (list wttrin--geolocation-sentinel "Honolulu, HI" "Tokyo")
+ (wttrin--sort-completions
+ (list "Honolulu, HI" wttrin--geolocation-sentinel "Tokyo")))))
+
+(ert-deftest test-wttrin-geolocation-sentinel-boundary-sort-no-sentinel-unchanged ()
+ "Boundary: a list without the sentinel is returned in its original order."
+ (should (equal '("Honolulu, HI" "Tokyo")
+ (wttrin--sort-completions '("Honolulu, HI" "Tokyo")))))
+
+(ert-deftest test-wttrin-geolocation-sentinel-boundary-sort-empty ()
+ "Boundary: an empty candidate list sorts to empty."
+ (should (null (wttrin--sort-completions nil))))
+
+;;; wttrin--completion-table — metadata + completion
+
+(ert-deftest test-wttrin-geolocation-sentinel-normal-table-metadata-sort-fn ()
+ "Normal: the table advertises the pin-first display-sort-function."
+ (let* ((table (wttrin--completion-table
+ (list wttrin--geolocation-sentinel "Tokyo")))
+ (meta (funcall table "" nil 'metadata)))
+ (should (eq #'wttrin--sort-completions
+ (cdr (assq 'display-sort-function (cdr meta)))))))
+
+(ert-deftest test-wttrin-geolocation-sentinel-normal-table-completes-candidates ()
+ "Normal: the table completes over the candidates it was given."
+ (let ((table (wttrin--completion-table
+ (list wttrin--geolocation-sentinel "Tokyo" "Paris"))))
+ (should (equal (sort (list wttrin--geolocation-sentinel "Tokyo" "Paris")
+ #'string-lessp)
+ (sort (all-completions "" table) #'string-lessp)))))
+
+;;; wttrin interactive entry — delegates to routing
+
+(ert-deftest test-wttrin-geolocation-sentinel-normal-entry-delegates-to-query-selection ()
+ "Normal: the interactive `wttrin' command routes its picker selection
+through `wttrin--query-selection' (smoke test of the entry wrapper)."
+ (testutil-wttrin-setup)
+ (unwind-protect
+ (let ((routed nil))
+ (cl-letf (((symbol-function 'completing-read)
+ (lambda (&rest _) "London, GB"))
+ ((symbol-function 'wttrin--query-selection)
+ (lambda (loc) (setq routed loc))))
+ (call-interactively 'wttrin))
+ (should (equal "London, GB" routed)))
+ (testutil-wttrin-teardown)))
+
+;;; wttrin--query-selection — routing
+
+(ert-deftest test-wttrin-geolocation-sentinel-normal-typed-location-queries-literally ()
+ "Normal: a typed location is passed straight to `wttrin-query'."
+ (testutil-wttrin-setup)
+ (unwind-protect
+ (let ((captured nil))
+ (cl-letf (((symbol-function 'wttrin-query)
+ (lambda (loc) (setq captured loc))))
+ (wttrin--query-selection "Paris"))
+ (should (equal "Paris" captured)))
+ (testutil-wttrin-teardown)))
+
+(ert-deftest test-wttrin-geolocation-sentinel-normal-routes-to-detect-then-query ()
+ "Normal: selecting the sentinel detects, then queries the resolved city."
+ (testutil-wttrin-setup)
+ (unwind-protect
+ (let ((captured nil))
+ (cl-letf (((symbol-function 'wttrin-geolocation-detect)
+ (lambda (callback) (funcall callback "Austin, TX")))
+ ((symbol-function 'wttrin-query)
+ (lambda (loc) (setq captured loc)))
+ ((symbol-function 'message) (lambda (&rest _) nil)))
+ (wttrin--query-selection wttrin--geolocation-sentinel))
+ (should (equal "Austin, TX" captured)))
+ (testutil-wttrin-teardown)))
+
+(ert-deftest test-wttrin-geolocation-sentinel-error-detect-failure-no-query ()
+ "Error: a failed detection does not query and does not mutate the favorite."
+ (testutil-wttrin-setup)
+ (unwind-protect
+ (let ((queried nil)
+ (wttrin-favorite-location "New Orleans, LA"))
+ (cl-letf (((symbol-function 'wttrin-geolocation-detect)
+ (lambda (callback) (funcall callback nil)))
+ ((symbol-function 'wttrin-query)
+ (lambda (_loc) (setq queried t)))
+ ((symbol-function 'message) (lambda (&rest _) nil)))
+ (wttrin--query-selection wttrin--geolocation-sentinel))
+ (should-not queried)
+ (should (equal "New Orleans, LA" wttrin-favorite-location)))
+ (testutil-wttrin-teardown)))
+
+;;; sentinel never enters history
+
+(ert-deftest test-wttrin-geolocation-sentinel-boundary-never-added-to-history ()
+ "Boundary: the sentinel string is never recorded in location history."
+ (testutil-wttrin-setup)
+ (unwind-protect
+ (let ((wttrin-default-locations '())
+ (wttrin--location-history nil))
+ (wttrin--add-to-location-history wttrin--geolocation-sentinel)
+ (should (null wttrin--location-history)))
+ (testutil-wttrin-teardown)))
+
+;;; wttrin-geolocation-enabled — opt-out switch
+
+(ert-deftest test-wttrin-geolocation-sentinel-normal-disabled-hides-sentinel ()
+ "Normal: with geolocation disabled, the sentinel is not offered."
+ (testutil-wttrin-setup)
+ (unwind-protect
+ (let ((wttrin-geolocation-enabled nil)
+ (wttrin-favorite-location nil)
+ (wttrin-default-locations '("Honolulu, HI"))
+ (wttrin--location-history '("Tokyo")))
+ (should-not (member wttrin--geolocation-sentinel
+ (wttrin--completion-candidates)))
+ (should (equal '("Honolulu, HI" "Tokyo")
+ (wttrin--completion-candidates))))
+ (testutil-wttrin-teardown)))
+
+(ert-deftest test-wttrin-geolocation-sentinel-boundary-enabled-shows-sentinel ()
+ "Boundary: with geolocation enabled (default), the sentinel is offered first."
+ (testutil-wttrin-setup)
+ (unwind-protect
+ (let ((wttrin-geolocation-enabled t)
+ (wttrin-favorite-location nil)
+ (wttrin-default-locations '("Honolulu, HI"))
+ (wttrin--location-history nil))
+ (should (equal wttrin--geolocation-sentinel
+ (car (wttrin--completion-candidates)))))
+ (testutil-wttrin-teardown)))
+
+(ert-deftest test-wttrin-geolocation-sentinel-error-disabled-detect-then-query-no-detect ()
+ "Error: with geolocation disabled, detect-then-query does not detect or query."
+ (testutil-wttrin-setup)
+ (unwind-protect
+ (let ((detected nil)
+ (queried nil)
+ (wttrin-geolocation-enabled nil))
+ (cl-letf (((symbol-function 'wttrin-geolocation-detect)
+ (lambda (_cb) (setq detected t)))
+ ((symbol-function 'wttrin-query)
+ (lambda (_loc) (setq queried t)))
+ ((symbol-function 'message) (lambda (&rest _) nil)))
+ (wttrin--detect-then-query))
+ (should-not detected)
+ (should-not queried))
+ (testutil-wttrin-teardown)))
+
+(ert-deftest test-wttrin-geolocation-sentinel-boundary-disabled-favorite-no-autodetect ()
+ "Boundary: with geolocation disabled, the t-favorite auto-detect does not fire."
+ (testutil-wttrin-setup)
+ (unwind-protect
+ (let ((detected nil)
+ (wttrin-geolocation-enabled nil)
+ (wttrin--favorite-location-pending nil))
+ (cl-letf (((symbol-function 'wttrin-geolocation-detect)
+ (lambda (_cb) (setq detected t))))
+ (wttrin--start-favorite-location-detect))
+ (should-not detected)
+ (should-not wttrin--favorite-location-pending))
+ (testutil-wttrin-teardown)))
+
+(provide 'test-wttrin-geolocation-sentinel)
+;;; test-wttrin-geolocation-sentinel.el ends here
diff --git a/tests/test-wttrin-location-history.el b/tests/test-wttrin-location-history.el
index 61b495c..4af8235 100644
--- a/tests/test-wttrin-location-history.el
+++ b/tests/test-wttrin-location-history.el
@@ -113,31 +113,37 @@
;;; wttrin--completion-candidates
(ert-deftest test-wttrin-location-history-normal-candidates-defaults-then-history ()
- "Candidates list defaults first, then history."
+ "Candidates list the sentinel, then defaults, then history."
(test-wttrin-location-history-setup)
(unwind-protect
- (let ((wttrin-default-locations '("Honolulu, HI" "Berkeley, CA"))
+ (let ((wttrin-favorite-location nil)
+ (wttrin-default-locations '("Honolulu, HI" "Berkeley, CA"))
(wttrin--location-history '("Tokyo" "Paris")))
- (should (equal '("Honolulu, HI" "Berkeley, CA" "Tokyo" "Paris")
+ (should (equal (list wttrin--geolocation-sentinel
+ "Honolulu, HI" "Berkeley, CA" "Tokyo" "Paris")
(wttrin--completion-candidates))))
(test-wttrin-location-history-teardown)))
(ert-deftest test-wttrin-location-history-normal-candidates-only-defaults ()
- "With empty history, candidates are just the defaults."
+ "With empty history, candidates are the sentinel then the defaults."
(test-wttrin-location-history-setup)
(unwind-protect
- (let ((wttrin-default-locations '("Honolulu, HI"))
+ (let ((wttrin-favorite-location nil)
+ (wttrin-default-locations '("Honolulu, HI"))
(wttrin--location-history nil))
- (should (equal '("Honolulu, HI") (wttrin--completion-candidates))))
+ (should (equal (list wttrin--geolocation-sentinel "Honolulu, HI")
+ (wttrin--completion-candidates))))
(test-wttrin-location-history-teardown)))
(ert-deftest test-wttrin-location-history-normal-candidates-only-history ()
- "With empty defaults, candidates are just the history."
+ "With empty defaults, candidates are the sentinel then the history."
(test-wttrin-location-history-setup)
(unwind-protect
- (let ((wttrin-default-locations '())
+ (let ((wttrin-favorite-location nil)
+ (wttrin-default-locations '())
(wttrin--location-history '("Tokyo")))
- (should (equal '("Tokyo") (wttrin--completion-candidates))))
+ (should (equal (list wttrin--geolocation-sentinel "Tokyo")
+ (wttrin--completion-candidates))))
(test-wttrin-location-history-teardown)))
;;; wttrin-remove-location-history
diff --git a/tests/test-wttrin-make-default.el b/tests/test-wttrin-make-default.el
index 623200c..e715e12 100644
--- a/tests/test-wttrin-make-default.el
+++ b/tests/test-wttrin-make-default.el
@@ -143,7 +143,8 @@ stale cache and fetches fresh weather for the new location immediately."
(wttrin--location-history nil)
(wttrin-favorite-location "Reykjavik"))
(should (equal (wttrin--completion-candidates)
- '("Reykjavik" "Honolulu, HI" "Berkeley, CA")))))
+ (list wttrin--geolocation-sentinel
+ "Reykjavik" "Honolulu, HI" "Berkeley, CA")))))
;;; Boundary Cases
@@ -161,7 +162,7 @@ stale cache and fetches fresh weather for the new location immediately."
(wttrin--location-history '("Oslo, NO"))
(wttrin-favorite-location nil))
(should (equal (wttrin--completion-candidates)
- '("Honolulu, HI" "Oslo, NO")))))
+ (list wttrin--geolocation-sentinel "Honolulu, HI" "Oslo, NO")))))
;;; --------------------------------------------------------------------------
;;; keymap binding
diff --git a/tests/test-wttrin-requery.el b/tests/test-wttrin-requery.el
index d6a8beb..5d52b36 100644
--- a/tests/test-wttrin-requery.el
+++ b/tests/test-wttrin-requery.el
@@ -105,6 +105,8 @@ to the core requery function."
(test-wttrin-requery-setup)
(unwind-protect
(let ((offered-collection nil)
+ (wttrin-favorite-location nil)
+ (wttrin--location-history nil)
(wttrin-default-locations '("Paris" "London" "Tokyo")))
(cl-letf (((symbol-function 'completing-read)
(lambda (_prompt collection &rest _args)
@@ -113,7 +115,12 @@ to the core requery function."
((symbol-function 'wttrin--requery-location)
(lambda (_loc) nil)))
(wttrin-requery)
- (should (equal offered-collection '("Paris" "London" "Tokyo")))))
+ ;; The collection is now a completion table (a function) that pins
+ ;; the sentinel first; check the candidates it completes over.
+ (should (equal (list wttrin--geolocation-sentinel
+ "Paris" "London" "Tokyo")
+ (wttrin--sort-completions
+ (all-completions "" offered-collection))))))
(test-wttrin-requery-teardown)))
(ert-deftest test-wttrin-requery-boundary-single-default-prefills ()
diff --git a/tests/test-wttrin-set-location-from-geolocation.el b/tests/test-wttrin-set-location-from-geolocation.el
index 170d0fb..e7c3a97 100644
--- a/tests/test-wttrin-set-location-from-geolocation.el
+++ b/tests/test-wttrin-set-location-from-geolocation.el
@@ -118,5 +118,34 @@
messages)))
(test-wttrin-set-location-from-geolocation-teardown)))
+;;; Opt-out
+
+(ert-deftest test-wttrin-set-location-from-geolocation-boundary-disabled-no-detect ()
+ "Boundary: with geolocation disabled, the command neither detects nor sets."
+ (test-wttrin-set-location-from-geolocation-setup)
+ (setq wttrin-favorite-location "Pre-existing, Place")
+ (unwind-protect
+ (let ((detected nil)
+ (wttrin-geolocation-enabled nil))
+ (cl-letf (((symbol-function 'wttrin-geolocation-detect)
+ (lambda (_cb) (setq detected t)))
+ ((symbol-function 'message) (lambda (&rest _) nil)))
+ (wttrin-set-location-from-geolocation))
+ (should-not detected)
+ (should (string= "Pre-existing, Place" wttrin-favorite-location)))
+ (test-wttrin-set-location-from-geolocation-teardown)))
+
+;;; Deprecation
+
+(ert-deftest test-wttrin-set-location-from-geolocation-normal-marked-obsolete ()
+ "Normal: the command is marked obsolete with a steering message.
+The favorite-setting behavior is preserved (see the Normal cases above);
+this only asserts the obsolescence marker so callers get a deprecation
+notice steering them to the picker."
+ (let ((info (get 'wttrin-set-location-from-geolocation 'byte-obsolete-info)))
+ (should info)
+ ;; Option 1: a steering string, not an alias to another function.
+ (should (stringp (nth 0 info)))))
+
(provide 'test-wttrin-set-location-from-geolocation)
;;; test-wttrin-set-location-from-geolocation.el ends here