blob: e16f78747262a415f6a225f7c46acb6fa377abab (
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
|
;;; test-wttrin--fetch-url.el --- Tests for wttrin--fetch-url -*- lexical-binding: t; -*-
;; Copyright (C) 2024 Craig Jennings
;;; Commentary:
;; Unit tests for wttrin--fetch-url function.
;; Tests the common async URL fetching logic extracted during refactoring.
;;; Code:
(require 'ert)
(require 'wttrin)
;;; Normal Cases
(ert-deftest test-wttrin--fetch-url-normal-success-calls-callback-with-data ()
"Test that successful fetch calls callback with decoded data."
(let ((callback-called nil)
(callback-data nil))
;; Mock url-retrieve to simulate successful response
(cl-letf (((symbol-function 'url-retrieve)
(lambda (url callback)
;; Simulate successful HTTP response
(with-temp-buffer
(insert "HTTP/1.1 200 OK\r\n")
(insert "Content-Type: text/plain\r\n")
(insert "\r\n")
(insert "Weather data here")
(funcall callback nil)))))
(wttrin--fetch-url
"http://example.com/weather"
(lambda (data)
(setq callback-called t)
(setq callback-data data)))
;; Verify callback was called with correct data
(should callback-called)
(should (string= "Weather data here" callback-data)))))
(ert-deftest test-wttrin--fetch-url-normal-utf8-decoding ()
"Test that UTF-8 content is properly decoded."
(let ((callback-data nil))
(cl-letf (((symbol-function 'url-retrieve)
(lambda (url callback)
(with-temp-buffer
(insert "HTTP/1.1 200 OK\r\n\r\n")
(insert "Weather: ☀️ Sunny 中文")
(funcall callback nil)))))
(wttrin--fetch-url
"http://example.com/weather"
(lambda (data)
(setq callback-data data)))
(should (string-match-p "☀️" callback-data))
(should (string-match-p "中文" callback-data)))))
(ert-deftest test-wttrin--fetch-url-normal-headers-stripped ()
"Test that HTTP headers are correctly stripped from response."
(let ((callback-data nil))
(cl-letf (((symbol-function 'url-retrieve)
(lambda (url callback)
(with-temp-buffer
(insert "HTTP/1.1 200 OK\r\n")
(insert "Content-Type: text/plain\r\n")
(insert "Content-Length: 17\r\n")
(insert "\r\n")
(insert "Weather data here")
(funcall callback nil)))))
(wttrin--fetch-url
"http://example.com/weather"
(lambda (data)
(setq callback-data data)))
;; Headers should not be in the data
(should-not (string-match-p "HTTP/1.1" callback-data))
(should-not (string-match-p "Content-Type" callback-data))
(should (string= "Weather data here" callback-data)))))
;;; Boundary Cases
(ert-deftest test-wttrin--fetch-url-boundary-empty-response ()
"Test handling of empty response body."
(let ((callback-data nil))
(cl-letf (((symbol-function 'url-retrieve)
(lambda (url callback)
(with-temp-buffer
(insert "HTTP/1.1 200 OK\r\n\r\n")
;; Empty body
(funcall callback nil)))))
(wttrin--fetch-url
"http://example.com/weather"
(lambda (data)
(setq callback-data data)))
(should (string= "" callback-data)))))
(ert-deftest test-wttrin--fetch-url-boundary-large-response ()
"Test handling of large response body."
(let ((callback-data nil)
(large-body (make-string 10000 ?x)))
(cl-letf (((symbol-function 'url-retrieve)
(lambda (url callback)
(with-temp-buffer
(insert "HTTP/1.1 200 OK\r\n\r\n")
(insert large-body)
(funcall callback nil)))))
(wttrin--fetch-url
"http://example.com/weather"
(lambda (data)
(setq callback-data data)))
(should (= 10000 (length callback-data))))))
(ert-deftest test-wttrin--fetch-url-boundary-unix-line-endings ()
"Test handling of Unix-style line endings (LF only)."
(let ((callback-data nil))
(cl-letf (((symbol-function 'url-retrieve)
(lambda (url callback)
(with-temp-buffer
(insert "HTTP/1.1 200 OK\n")
(insert "Content-Type: text/plain\n")
(insert "\n")
(insert "Weather data")
(funcall callback nil)))))
(wttrin--fetch-url
"http://example.com/weather"
(lambda (data)
(setq callback-data data)))
(should (string= "Weather data" callback-data)))))
;;; Error Cases
(ert-deftest test-wttrin--fetch-url-error-network-error-calls-callback-with-nil ()
"Test that network errors result in callback being called with nil."
(let ((callback-called nil)
(callback-data 'not-nil))
(cl-letf (((symbol-function 'url-retrieve)
(lambda (url callback)
;; Simulate network error
(with-temp-buffer
(funcall callback '(:error (error "Network unreachable")))))))
(wttrin--fetch-url
"http://example.com/weather"
(lambda (data)
(setq callback-called t)
(setq callback-data data)))
(should callback-called)
(should (null callback-data)))))
(ert-deftest test-wttrin--fetch-url-error-buffer-killed-after-processing ()
"Test that response buffer is properly killed after processing."
(let ((buffers-before (buffer-list))
(callback-called nil))
(cl-letf (((symbol-function 'url-retrieve)
(lambda (url callback)
(with-temp-buffer
(insert "HTTP/1.1 200 OK\r\n\r\ndata")
(funcall callback nil)))))
(wttrin--fetch-url
"http://example.com/weather"
(lambda (data)
(setq callback-called t)))
(should callback-called)
;; Buffer list should be the same (no leaked buffers)
(should (= (length buffers-before) (length (buffer-list)))))))
(provide 'test-wttrin--fetch-url)
;;; test-wttrin--fetch-url.el ends here
|