blob: a44040a8d4bc3d665d659107b645bb205fc47ea5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
;;; test-wttrin-query.el --- Tests for wttrin-query -*- lexical-binding: t; -*-
;; Copyright (C) 2025 Craig Jennings
;;; Commentary:
;; Unit tests for wttrin-query function.
;; Tests the async weather query orchestration: buffer creation,
;; loading state, cache lookup, and display callback.
;;; Code:
(require 'ert)
(require 'wttrin)
(require 'testutil-wttrin)
;;; Setup and Teardown
(defun test-wttrin-query-setup ()
"Setup for wttrin-query tests."
(testutil-wttrin-setup)
(when (get-buffer "*wttr.in*")
(kill-buffer "*wttr.in*")))
(defun test-wttrin-query-teardown ()
"Teardown for wttrin-query tests."
(testutil-wttrin-teardown)
(when (get-buffer "*wttr.in*")
(kill-buffer "*wttr.in*")))
;;; Normal Cases
(ert-deftest test-wttrin-query-normal-creates-buffer ()
"Calling query should create the *wttr.in* buffer."
(test-wttrin-query-setup)
(unwind-protect
(cl-letf (((symbol-function 'wttrin--get-cached-or-fetch)
(lambda (_location _callback) nil)))
(wttrin-query "Paris")
(should (get-buffer "*wttr.in*")))
(test-wttrin-query-teardown)))
(ert-deftest test-wttrin-query-normal-shows-loading-message ()
"Buffer should show a loading message with the location name while fetching."
(test-wttrin-query-setup)
(unwind-protect
(cl-letf (((symbol-function 'wttrin--get-cached-or-fetch)
(lambda (_location _callback) nil)))
(wttrin-query "New Orleans, LA")
(with-current-buffer "*wttr.in*"
(let ((contents (buffer-string)))
(should (string-match-p "Loading" contents))
(should (string-match-p "New Orleans, LA" contents)))))
(test-wttrin-query-teardown)))
(ert-deftest test-wttrin-query-normal-buffer-is-read-only-during-loading ()
"The loading buffer should be read-only to prevent user edits."
(test-wttrin-query-setup)
(unwind-protect
(cl-letf (((symbol-function 'wttrin--get-cached-or-fetch)
(lambda (_location _callback) nil)))
(wttrin-query "Tokyo")
(with-current-buffer "*wttr.in*"
(should buffer-read-only)))
(test-wttrin-query-teardown)))
(ert-deftest test-wttrin-query-normal-fetches-for-correct-location ()
"Query should request weather for the specified location."
(test-wttrin-query-setup)
(unwind-protect
(let ((fetched-location nil))
(cl-letf (((symbol-function 'wttrin--get-cached-or-fetch)
(lambda (location _callback)
(setq fetched-location location))))
(wttrin-query "Berlin, DE")
(should (equal fetched-location "Berlin, DE"))))
(test-wttrin-query-teardown)))
;;; Boundary Cases
(ert-deftest test-wttrin-query-boundary-dead-buffer-callback-is-safe ()
"If the buffer is killed before the async callback fires, it should not error."
(test-wttrin-query-setup)
(unwind-protect
(let ((saved-callback nil))
(cl-letf (((symbol-function 'wttrin--get-cached-or-fetch)
(lambda (_location callback)
(setq saved-callback callback))))
(wttrin-query "Paris")
;; Kill the buffer before callback fires
(kill-buffer "*wttr.in*")
;; Invoke callback — should not error
(should-not (get-buffer "*wttr.in*"))
(funcall saved-callback "weather data")
;; Buffer should NOT be recreated
(should-not (get-buffer "*wttr.in*"))))
(test-wttrin-query-teardown)))
;;; Error Cases
(ert-deftest test-wttrin-query-error-nil-response-shows-error-message ()
"When fetch returns nil, the user should see an error message, not a crash."
(test-wttrin-query-setup)
(unwind-protect
(let ((saved-callback nil)
(displayed-message nil))
(cl-letf (((symbol-function 'wttrin--get-cached-or-fetch)
(lambda (_location callback)
(setq saved-callback callback)))
((symbol-function 'message)
(lambda (fmt &rest args)
(setq displayed-message (apply #'format fmt args)))))
(wttrin-query "BadLocation")
;; Simulate fetch returning nil
(funcall saved-callback nil)
;; Should have shown error message (from wttrin--display-weather validation)
(should displayed-message)
(should (string-match-p "Cannot retrieve" displayed-message))))
(test-wttrin-query-teardown)))
(provide 'test-wttrin-query)
;;; test-wttrin-query.el ends here
|