summaryrefslogtreecommitdiff
path: root/tests/test-wttrin-integration-with-debug.el
blob: 4b122bf66268428551c84cfc68f67448ed131600 (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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
;;; test-wttrin-integration-with-debug.el --- Integration test with debug enabled -*- lexical-binding: t; -*-

;; Copyright (C) 2024 Craig Jennings

;;; Commentary:
;; Comprehensive integration test that:
;; 1. Enables debug mode
;; 2. Mocks weather fetch to avoid network calls
;; 3. Tests mode-line display with real weather data
;; 4. Verifies debug log captures key events

;;; Code:

(require 'ert)
(require 'wttrin)

;; Sample weather data from wttr.in custom format API
(defconst test-wttrin-sample-weather-data
  "Berkeley, CA: ☀️ +62°F Clear"
  "Sample weather data in wttr.in custom format.")

(defconst test-wttrin-sample-full-weather
  "Weather for Berkeley, CA

     \\    /      Clear
      .-.       62 °F
   ― (   ) ―    ↑ 5 mph
      `-'       10 mi
     /    \\     0.0 in"
  "Sample full weather display data.")

;;; Setup and Teardown

(defun test-wttrin-setup ()
  "Set up test environment with debug enabled."
  ;; Enable debug mode
  (setq wttrin-debug t)
  ;; Load debug module if not already loaded
  (unless (featurep 'wttrin-debug)
    (require 'wttrin-debug))
  ;; Clear any existing debug log
  (wttrin-debug-clear-log)
  ;; Clear cache
  (wttrin-clear-cache)
  ;; Set test configuration
  (setq wttrin-mode-line-favorite-location "Berkeley, CA")
  (setq wttrin-mode-line-startup-delay 1)  ; Minimum valid value
  (setq wttrin-unit-system "m"))

(defun test-wttrin-teardown ()
  "Clean up after tests."
  (when (boundp 'wttrin-mode-line-mode)
    (wttrin-mode-line-mode -1))
  (wttrin-clear-cache)
  (wttrin-debug-clear-log)
  (setq wttrin-mode-line-string nil)
  (setq wttrin--mode-line-tooltip-data nil))

;;; Mock URL Fetching

(defvar test-wttrin--original-fetch-url nil
  "Original wttrin--fetch-url function for restoration after test.")

(defun test-wttrin-mock-fetch (url callback)
  "Mock version of wttrin--fetch-url that returns fake weather data.
URL is ignored. CALLBACK is called with mock data."
  (when (featurep 'wttrin-debug)
    (wttrin--debug-log "MOCK-FETCH: Called with URL: %s" url))
  ;; Call callback directly (synchronous) since run-at-time doesn't work well in batch mode
  (when (featurep 'wttrin-debug)
    (wttrin--debug-log "MOCK-FETCH: Calling callback with mock data"))
  (funcall callback test-wttrin-sample-weather-data))

(defmacro with-mocked-fetch (&rest body)
  "Execute BODY with wttrin--fetch-url mocked to return test data."
  `(let ((test-wttrin--original-fetch-url (symbol-function 'wttrin--fetch-url)))
     (unwind-protect
         (progn
           (fset 'wttrin--fetch-url #'test-wttrin-mock-fetch)
           ,@body)
       (fset 'wttrin--fetch-url test-wttrin--original-fetch-url))))

;;; Integration Tests

(ert-deftest test-wttrin-debug-integration-mode-line-fetch-and-display ()
  "Integration test: Fetch weather and verify mode-line display with debug logging."
  (test-wttrin-setup)
  (unwind-protect
      (with-mocked-fetch
       ;; Clear debug log
       (wttrin-debug-clear-log)

       ;; Fetch weather for mode-line
       (wttrin--mode-line-fetch-weather)

       ;; Wait for async callback to complete (mocked, so should be fast)
       (sleep-for 0.1)

       ;; Verify mode-line string was set
       (should wttrin-mode-line-string)
       (should (stringp wttrin-mode-line-string))
       (should (string-match-p "☀" wttrin-mode-line-string))  ; Should contain emoji

       ;; Verify tooltip data was set
       (should wttrin--mode-line-tooltip-data)
       (should (string= test-wttrin-sample-weather-data wttrin--mode-line-tooltip-data))

       ;; Verify debug log captured key events
       (let ((log-messages (mapcar #'cdr wttrin--debug-log)))
         ;; Should have logged the fetch start
         (should (seq-some (lambda (msg) (string-match-p "mode-line-fetch: Starting" msg))
                          log-messages))
         ;; Should have logged receiving data
         (should (seq-some (lambda (msg) (string-match-p "mode-line-fetch: Received data" msg))
                          log-messages))
         ;; Should have logged display update
         (should (seq-some (lambda (msg) (string-match-p "mode-line-display:" msg))
                          log-messages))
         ;; Should have logged emoji extraction
         (should (seq-some (lambda (msg) (string-match-p "Extracted emoji" msg))
                          log-messages))))
    (test-wttrin-teardown)))

(ert-deftest test-wttrin-debug-integration-full-weather-query ()
  "Integration test: Query full weather and verify debug logging."
  (test-wttrin-setup)
  (unwind-protect
      (progn
        ;; Clear debug log
        (wttrin-debug-clear-log)

        ;; Mock full weather fetch (synchronous for batch mode)
        (cl-letf (((symbol-function 'wttrin--fetch-url)
                   (lambda (url callback)
                     (when (featurep 'wttrin-debug)
                       (wttrin--debug-log "MOCK-FETCH: Full weather query for URL: %s" url))
                     ;; Call directly instead of using run-at-time (doesn't work in batch)
                     (funcall callback test-wttrin-sample-full-weather))))

          ;; Start the query (now synchronous with mocked fetch)
          (wttrin-query "Berkeley, CA")

          ;; Verify buffer was created
          (should (get-buffer "*wttr.in*"))

          ;; Verify debug log shows mock was called
          (let ((log-messages (mapcar #'cdr wttrin--debug-log)))
            ;; Should have logged the mock fetch
            (should (seq-some (lambda (msg) (string-match-p "MOCK-FETCH: Full weather query" msg))
                             log-messages)))))
    ;; Cleanup
    (when (get-buffer "*wttr.in*")
      (kill-buffer "*wttr.in*"))
    (test-wttrin-teardown)))

(ert-deftest test-wttrin-debug-integration-mode-line-mode-toggle ()
  "Integration test: Toggle mode-line mode and verify debug logging."
  (test-wttrin-setup)
  (unwind-protect
      (with-mocked-fetch
       ;; Clear debug log
       (wttrin-debug-clear-log)

       ;; Enable mode-line mode
       (wttrin-mode-line-mode 1)
       (should wttrin-mode-line-mode)

       ;; Manually trigger the initial fetch instead of waiting for timer
       ;; (timers don't process well in batch mode)
       (wttrin--mode-line-fetch-weather)

       ;; Verify mode-line string is set
       (should wttrin-mode-line-string)

       ;; Verify global-mode-string contains our widget
       (should (member 'wttrin-mode-line-string global-mode-string))

       ;; Disable mode-line mode
       (wttrin-mode-line-mode -1)
       (should-not wttrin-mode-line-mode)

       ;; Verify mode-line string is cleared
       (should-not wttrin-mode-line-string)

       ;; Verify removed from global-mode-string
       (should-not (member 'wttrin-mode-line-string global-mode-string)))
    (test-wttrin-teardown)))

(ert-deftest test-wttrin-debug-integration-error-handling ()
  "Integration test: Verify debug logging captures errors correctly."
  (test-wttrin-setup)
  (unwind-protect
      (progn
        ;; Clear debug log
        (wttrin-debug-clear-log)

        ;; Mock fetch that returns nil (simulating network error)
        (cl-letf (((symbol-function 'wttrin--fetch-url)
                   (lambda (url callback)
                     (when (featurep 'wttrin-debug)
                       (wttrin--debug-log "MOCK-FETCH: Simulating error for URL: %s" url))
                     (run-at-time 0 nil (lambda () (funcall callback nil))))))

          ;; Try to fetch (should handle error gracefully)
          (wttrin--mode-line-fetch-weather)

          ;; Wait for async callback
          (sleep-for 0.1)

          ;; Verify error was logged
          (let ((log-messages (mapcar #'cdr wttrin--debug-log)))
            (should (seq-some (lambda (msg) (string-match-p "No data received" msg))
                             log-messages)))))
    (test-wttrin-teardown)))

(ert-deftest test-wttrin-debug-integration-log-inspection ()
  "Integration test: Verify debug log can be inspected programmatically."
  (test-wttrin-setup)
  (unwind-protect
      (progn
        ;; Clear and add some test log entries
        (wttrin-debug-clear-log)
        (wttrin--debug-log "Test message 1")
        (wttrin--debug-log "Test message 2 with arg: %s" "value")

        ;; Verify log structure
        (should (= 2 (length wttrin--debug-log)))
        (should (consp (car wttrin--debug-log)))  ; Each entry is (timestamp . message)
        (should (stringp (caar wttrin--debug-log)))  ; Timestamp is string
        (should (stringp (cdar wttrin--debug-log)))  ; Message is string

        ;; Verify messages
        (let ((messages (mapcar #'cdr wttrin--debug-log)))
          (should (member "Test message 1" messages))
          (should (seq-some (lambda (msg) (string-match-p "Test message 2.*value" msg))
                           messages)))

        ;; Clear log
        (wttrin-debug-clear-log)
        (should (= 0 (length wttrin--debug-log))))
    (test-wttrin-teardown)))

(provide 'test-wttrin-integration-with-debug)
;;; test-wttrin-integration-with-debug.el ends here