diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test-wttrin-geolocation-sentinel.el | 212 | ||||
| -rw-r--r-- | tests/test-wttrin-location-history.el | 24 | ||||
| -rw-r--r-- | tests/test-wttrin-make-default.el | 5 | ||||
| -rw-r--r-- | tests/test-wttrin-requery.el | 9 | ||||
| -rw-r--r-- | tests/test-wttrin-set-location-from-geolocation.el | 29 |
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 |
