AtlatestRepositorysigil-youtube

sigil-youtube / tree / testyoutube-test.sgl

1;;; Tests for (youtube) — core module
2;;;
3;;; Tests record construction, JSON response parsing, URL building,
4;;; and query string encoding using fixture data (no real API calls).
5
6(import (sigil core)
7 (sigil dict)
8 (sigil string)
9 (sigil struct)
10 (sigil json)
11 (sigil test)
12 (only (sigil http) url-encode-value build-query-string)
13 (youtube))
15;; ---------------------------------------------------------------
16;; Test fixtures — JSON response samples
17;; ---------------------------------------------------------------
19(define video-resource-json
20 (json-decode
21 (string-append
22 "{\"id\": \"dQw4w9WgXcQ\","
23 " \"snippet\": {"
24 " \"title\": \"Test Video\","
25 " \"description\": \"A test description\","
26 " \"tags\": [\"test\", \"sigil\", \"youtube\"],"
27 " \"categoryId\": \"28\","
28 " \"publishedAt\": \"2026-03-20T12:00:00Z\""
29 " },"
30 " \"status\": {"
31 " \"privacyStatus\": \"public\""
32 " },"
33 " \"statistics\": {"
34 " \"viewCount\": \"1234\","
35 " \"likeCount\": \"56\","
36 " \"commentCount\": \"7\""
37 " }}")))
39(define video-no-tags-json
40 (json-decode
41 (string-append
42 "{\"id\": \"abc123\","
43 " \"snippet\": {"
44 " \"title\": \"No Tags Video\","
45 " \"description\": \"\""
46 " },"
47 " \"status\": {},"
48 " \"statistics\": {}}")))
50(define channel-resource-json
51 (json-decode
52 (string-append
53 "{\"id\": \"UCxxxxxxxxxxxxxx\","
54 " \"snippet\": {"
55 " \"title\": \"System Crafters\""
56 " },"
57 " \"statistics\": {"
58 " \"subscriberCount\": \"50000\","
59 " \"videoCount\": \"300\""
60 " },"
61 " \"contentDetails\": {"
62 " \"relatedPlaylists\": {"
63 " \"uploads\": \"UUxxxxxxxxxxxxxx\""
64 " }"
65 " }}")))
67(define channel-minimal-json
68 (json-decode
69 (string-append
70 "{\"id\": \"UCyyyy\","
71 " \"snippet\": {},"
72 " \"statistics\": {},"
73 " \"contentDetails\": {}}")))
75;; ---------------------------------------------------------------
76;; Client construction tests
77;; ---------------------------------------------------------------
79(test-group "client construction"
81 (test "client with access token"
82 (let ((c (youtube-client access-token: "ya29.test-token")))
83 (assert-true (youtube-client? c))
84 (assert-equal "ya29.test-token" (youtube-client-access-token c))
85 (assert-equal #f (youtube-client-api-key c))
86 (assert-equal "https://www.googleapis.com/youtube/v3"
87 (youtube-client-base-url c))))
89 (test "client with api key only"
90 (let ((c (youtube-client api-key: "AIzaTest123")))
91 (assert-equal #f (youtube-client-access-token c))
92 (assert-equal "AIzaTest123" (youtube-client-api-key c))))
94 (test "client with both tokens"
95 (let ((c (youtube-client access-token: "ya29.tok"
96 api-key: "AIza.key")))
97 (assert-equal "ya29.tok" (youtube-client-access-token c))
98 (assert-equal "AIza.key" (youtube-client-api-key c))))
100 (test "custom base url"
101 (let ((c (youtube-client access-token: "tok"
102 base-url: "http://localhost:8080")))
103 (assert-equal "http://localhost:8080"
104 (youtube-client-base-url c)))))
106;; ---------------------------------------------------------------
107;; Video record tests
108;; ---------------------------------------------------------------
110(test-group "video records"
112 (test "video record construction"
113 (let ((v (youtube-video id: "vid1" title: "My Video"
114 description: "desc" tags: '("a" "b")
115 category-id: "22"
116 privacy-status: "unlisted")))
117 (assert-true (youtube-video? v))
118 (assert-equal "vid1" (youtube-video-id v))
119 (assert-equal "My Video" (youtube-video-title v))
120 (assert-equal "desc" (youtube-video-description v))
121 (assert-equal '("a" "b") (youtube-video-tags v))
122 (assert-equal "22" (youtube-video-category-id v))
123 (assert-equal "unlisted" (youtube-video-privacy-status v))))
125 (test "video record defaults"
126 (let ((v (youtube-video id: "vid2")))
127 (assert-equal "" (youtube-video-title v))
128 (assert-equal "" (youtube-video-description v))
129 (assert-equal '() (youtube-video-tags v))
130 (assert-equal #f (youtube-video-category-id v))
131 (assert-equal "private" (youtube-video-privacy-status v))
132 (assert-equal #f (youtube-video-published-at v)))))
134;; ---------------------------------------------------------------
135;; Channel record tests
136;; ---------------------------------------------------------------
138(test-group "channel records"
140 (test "channel record construction"
141 (let ((ch (youtube-channel id: "UC123" title: "My Channel"
142 subscriber-count: 1000
143 video-count: 50
144 uploads-playlist-id: "UU123")))
145 (assert-true (youtube-channel? ch))
146 (assert-equal "UC123" (youtube-channel-id ch))
147 (assert-equal "My Channel" (youtube-channel-title ch))
148 (assert-equal 1000 (youtube-channel-subscriber-count ch))
149 (assert-equal 50 (youtube-channel-video-count ch))
150 (assert-equal "UU123" (youtube-channel-uploads-playlist-id ch))))
152 (test "channel record defaults"
153 (let ((ch (youtube-channel id: "UC456")))
154 (assert-equal "" (youtube-channel-title ch))
155 (assert-equal 0 (youtube-channel-subscriber-count ch))
156 (assert-equal 0 (youtube-channel-video-count ch))
157 (assert-equal #f (youtube-channel-uploads-playlist-id ch)))))
159;; ---------------------------------------------------------------
160;; Video parsing tests
161;; ---------------------------------------------------------------
163(test-group "video parsing"
165 (test "parse full video resource"
166 (let ((v (parse-video video-resource-json)))
167 (assert-true (youtube-video? v))
168 (assert-equal "dQw4w9WgXcQ" (youtube-video-id v))
169 (assert-equal "Test Video" (youtube-video-title v))
170 (assert-equal "A test description" (youtube-video-description v))
171 (assert-equal '("test" "sigil" "youtube") (youtube-video-tags v))
172 (assert-equal "28" (youtube-video-category-id v))
173 (assert-equal "public" (youtube-video-privacy-status v))
174 (assert-equal "2026-03-20T12:00:00Z" (youtube-video-published-at v))))
176 (test "parse video statistics"
177 (let ((v (parse-video video-resource-json)))
178 (let ((stats (youtube-video-statistics v)))
179 (assert-true (dict? stats))
180 (assert-equal "1234" (dict-ref stats viewCount:))
181 (assert-equal "56" (dict-ref stats likeCount:)))))
183 (test "parse video with missing tags"
184 (let ((v (parse-video video-no-tags-json)))
185 (assert-equal "abc123" (youtube-video-id v))
186 (assert-equal "No Tags Video" (youtube-video-title v))
187 (assert-equal '() (youtube-video-tags v)))))
189;; ---------------------------------------------------------------
190;; Channel parsing tests
191;; ---------------------------------------------------------------
193(test-group "channel parsing"
195 (test "parse full channel resource"
196 (let ((ch (parse-channel channel-resource-json)))
197 (assert-true (youtube-channel? ch))
198 (assert-equal "UCxxxxxxxxxxxxxx" (youtube-channel-id ch))
199 (assert-equal "System Crafters" (youtube-channel-title ch))
200 (assert-equal 50000 (youtube-channel-subscriber-count ch))
201 (assert-equal 300 (youtube-channel-video-count ch))
202 (assert-equal "UUxxxxxxxxxxxxxx"
203 (youtube-channel-uploads-playlist-id ch))))
205 (test "parse minimal channel resource"
206 (let ((ch (parse-channel channel-minimal-json)))
207 (assert-equal "UCyyyy" (youtube-channel-id ch))
208 (assert-equal "" (youtube-channel-title ch))
209 (assert-equal 0 (youtube-channel-subscriber-count ch))
210 (assert-equal 0 (youtube-channel-video-count ch))
211 (assert-equal #f (youtube-channel-uploads-playlist-id ch)))))
213;; ---------------------------------------------------------------
214;; URL encoding tests
215;; ---------------------------------------------------------------
217(test-group "URL encoding"
219 (test "encode simple string"
220 (assert-equal "hello" (url-encode-value "hello")))
222 (test "encode spaces"
223 (assert-equal "hello+world" (url-encode-value "hello world")))
225 (test "encode special characters"
226 (assert-equal "foo%26bar" (url-encode-value "foo&bar")))
228 (test "encode equals sign"
229 (assert-equal "key%3Dvalue" (url-encode-value "key=value")))
231 (test "preserve unreserved characters"
232 (assert-equal "a-b_c.d~e" (url-encode-value "a-b_c.d~e"))))
234;; ---------------------------------------------------------------
235;; Query string building tests
236;; ---------------------------------------------------------------
238(test-group "query string building"
240 (test "build simple query string"
241 (assert-equal "?part=snippet&id=abc123"
242 (build-query-string
243 (list (cons "part" "snippet")
244 (cons "id" "abc123")))))
246 (test "omit false values"
247 (assert-equal "?part=snippet"
248 (build-query-string
249 (list (cons "part" "snippet")
250 (cons "pageToken" #f)))))
252 (test "empty params"
253 (assert-equal ""
254 (build-query-string '())))
256 (test "encode values in query string"
257 (assert-equal "?q=hello+world"
258 (build-query-string
259 (list (cons "q" "hello world"))))))
261;; ---------------------------------------------------------------
262;; Auth headers tests
263;; ---------------------------------------------------------------
265(test-group "auth headers"
267 (test "bearer token header"
268 (let* ((c (youtube-client access-token: "ya29.test"))
269 (headers (youtube-auth-headers c)))
270 (assert-equal "Bearer ya29.test"
271 (dict-ref headers authorization:))))
273 (test "no header without token"
274 (let* ((c (youtube-client api-key: "AIza.key"))
275 (headers (youtube-auth-headers c)))
276 (assert-equal #f (dict-ref headers authorization: #f)))))
278;; ---------------------------------------------------------------
279;; Page info parsing tests
280;; ---------------------------------------------------------------
282(test-group "page info parsing"
284 (test "parse page info with next token"
285 (let ((data #{ pageInfo: #{ totalResults: 42 }
286 nextPageToken: "CDIQAA" }))
287 (let ((info (parse-page-info data)))
288 (assert-equal 42 (dict-ref info total-results:))
289 (assert-equal "CDIQAA" (dict-ref info next-page-token:)))))
291 (test "parse page info without next token"
292 (let ((data #{ pageInfo: #{ totalResults: 5 } }))
293 (let ((info (parse-page-info data)))
294 (assert-equal 5 (dict-ref info total-results:))
295 (assert-equal #f (dict-ref info next-page-token:))))))
297(run-tests)