AtlatestRepositorysigil-twitch
sigil-twitch / tree / testtwitch-test.sgl
1
;;; Tests for (twitch) — core module2
;;;3
;;; Tests record construction, JSON response parsing, URL building,4
;;; and query string encoding using fixture data (no real API calls).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
(twitch))15
;; ---------------------------------------------------------------16
;; Test fixtures — JSON response samples17
;; ---------------------------------------------------------------19
(define channel-resource-json20
(json-decode21
(string-append22
"{\"broadcaster_id\": \"141981764\","23
" \"broadcaster_login\": \"twitchdev\","24
" \"broadcaster_name\": \"TwitchDev\","25
" \"game_name\": \"Science & Technology\","26
" \"game_id\": \"509670\","27
" \"title\": \"Building cool stuff\","28
" \"tags\": [\"English\", \"Coding\"]}")))30
(define channel-minimal-json31
(json-decode32
(string-append33
"{\"broadcaster_id\": \"12345\","34
" \"broadcaster_name\": \"MinimalUser\"}")))36
(define stream-resource-json37
(json-decode38
(string-append39
"{\"id\": \"40944942733\","40
" \"user_id\": \"141981764\","41
" \"user_name\": \"TwitchDev\","42
" \"game_name\": \"Science & Technology\","43
" \"title\": \"Live coding session\","44
" \"viewer_count\": 1234,"45
" \"started_at\": \"2026-03-25T14:00:00Z\"}")))47
(define stream-minimal-json48
(json-decode49
(string-append50
"{\"id\": \"99999\","51
" \"user_id\": \"11111\"}")))53
(define user-resource-json54
(json-decode55
(string-append56
"{\"id\": \"141981764\","57
" \"login\": \"twitchdev\","58
" \"display_name\": \"TwitchDev\","59
" \"type\": \"\","60
" \"broadcaster_type\": \"partner\","61
" \"description\": \"Supporting devs\","62
" \"profile_image_url\": \"https://example.com/pic.png\","63
" \"created_at\": \"2016-12-14T20:32:28Z\"}")))65
(define user-minimal-json66
(json-decode67
(string-append68
"{\"id\": \"54321\","69
" \"login\": \"testuser\"}")))71
;; ---------------------------------------------------------------72
;; Client construction tests73
;; ---------------------------------------------------------------75
(test-group "client construction"77
(test "client with credentials"78
(let ((c (twitch-client client-id: "abc123"79
access-token: "oauth-token")))80
(assert-true (twitch-client? c))81
(assert-equal "abc123" (twitch-client-client-id c))82
(assert-equal "oauth-token" (twitch-client-access-token c))83
(assert-equal "https://api.twitch.tv/helix"84
(twitch-client-base-url c))))86
(test "custom base url"87
(let ((c (twitch-client client-id: "id"88
access-token: "tok"89
base-url: "http://localhost:8080/mock")))90
(assert-equal "http://localhost:8080/mock"91
(twitch-client-base-url c)))))93
;; ---------------------------------------------------------------94
;; Auth headers tests95
;; ---------------------------------------------------------------97
(test-group "auth headers"99
(test "headers include both client-id and bearer token"100
(let* ((c (twitch-client client-id: "my-client-id"101
access-token: "my-token"))102
(headers (twitch-auth-headers c)))103
(assert-equal "Bearer my-token"104
(dict-ref headers authorization:))105
(assert-equal "my-client-id"106
(dict-ref headers client-id:)))))108
;; ---------------------------------------------------------------109
;; Channel record tests110
;; ---------------------------------------------------------------112
(test-group "channel records"114
(test "channel record construction"115
(let ((ch (twitch-channel id: "12345" name: "TestChannel"116
game-name: "Just Chatting"117
game-id: "509658"118
title: "Hello!"119
tags: '("English" "Coding"))))120
(assert-true (twitch-channel? ch))121
(assert-equal "12345" (twitch-channel-id ch))122
(assert-equal "TestChannel" (twitch-channel-name ch))123
(assert-equal "Just Chatting" (twitch-channel-game-name ch))124
(assert-equal "509658" (twitch-channel-game-id ch))125
(assert-equal "Hello!" (twitch-channel-title ch))126
(assert-equal '("English" "Coding") (twitch-channel-tags ch))))128
(test "channel record defaults"129
(let ((ch (twitch-channel id: "99")))130
(assert-equal "" (twitch-channel-name ch))131
(assert-equal "" (twitch-channel-game-name ch))132
(assert-equal "" (twitch-channel-game-id ch))133
(assert-equal "" (twitch-channel-title ch))134
(assert-equal '() (twitch-channel-tags ch)))))136
;; ---------------------------------------------------------------137
;; Stream record tests138
;; ---------------------------------------------------------------140
(test-group "stream records"142
(test "stream record construction"143
(let ((s (twitch-stream id: "40944942733"144
user-id: "141981764"145
user-name: "TwitchDev"146
game-name: "Science & Technology"147
title: "Live coding"148
viewer-count: 500149
started-at: "2026-03-25T14:00:00Z")))150
(assert-true (twitch-stream? s))151
(assert-equal "40944942733" (twitch-stream-id s))152
(assert-equal "141981764" (twitch-stream-user-id s))153
(assert-equal 500 (twitch-stream-viewer-count s))))155
(test "stream record defaults"156
(let ((s (twitch-stream id: "1")))157
(assert-equal "" (twitch-stream-user-id s))158
(assert-equal 0 (twitch-stream-viewer-count s))159
(assert-equal #f (twitch-stream-started-at s)))))161
;; ---------------------------------------------------------------162
;; User record tests163
;; ---------------------------------------------------------------165
(test-group "user records"167
(test "user record construction"168
(let ((u (twitch-user id: "141981764"169
login: "twitchdev"170
display-name: "TwitchDev"171
broadcaster-type: "partner")))172
(assert-true (twitch-user? u))173
(assert-equal "141981764" (twitch-user-id u))174
(assert-equal "twitchdev" (twitch-user-login u))175
(assert-equal "partner" (twitch-user-broadcaster-type u))))177
(test "user record defaults"178
(let ((u (twitch-user id: "1")))179
(assert-equal "" (twitch-user-login u))180
(assert-equal "" (twitch-user-display-name u))181
(assert-equal "" (twitch-user-type u))182
(assert-equal #f (twitch-user-created-at u)))))184
;; ---------------------------------------------------------------185
;; Channel parsing tests186
;; ---------------------------------------------------------------188
(test-group "channel parsing"190
(test "parse full channel resource"191
(let ((ch (parse-channel channel-resource-json)))192
(assert-true (twitch-channel? ch))193
(assert-equal "141981764" (twitch-channel-id ch))194
(assert-equal "TwitchDev" (twitch-channel-name ch))195
(assert-equal "Science & Technology" (twitch-channel-game-name ch))196
(assert-equal "509670" (twitch-channel-game-id ch))197
(assert-equal "Building cool stuff" (twitch-channel-title ch))198
(assert-equal '("English" "Coding") (twitch-channel-tags ch))))200
(test "parse minimal channel resource"201
(let ((ch (parse-channel channel-minimal-json)))202
(assert-equal "12345" (twitch-channel-id ch))203
(assert-equal "MinimalUser" (twitch-channel-name ch))204
(assert-equal "" (twitch-channel-game-name ch))205
(assert-equal '() (twitch-channel-tags ch)))))207
;; ---------------------------------------------------------------208
;; Stream parsing tests209
;; ---------------------------------------------------------------211
(test-group "stream parsing"213
(test "parse full stream resource"214
(let ((s (parse-stream stream-resource-json)))215
(assert-true (twitch-stream? s))216
(assert-equal "40944942733" (twitch-stream-id s))217
(assert-equal "141981764" (twitch-stream-user-id s))218
(assert-equal "TwitchDev" (twitch-stream-user-name s))219
(assert-equal "Science & Technology" (twitch-stream-game-name s))220
(assert-equal "Live coding session" (twitch-stream-title s))221
(assert-equal 1234 (twitch-stream-viewer-count s))222
(assert-equal "2026-03-25T14:00:00Z" (twitch-stream-started-at s))))224
(test "parse minimal stream resource"225
(let ((s (parse-stream stream-minimal-json)))226
(assert-equal "99999" (twitch-stream-id s))227
(assert-equal "11111" (twitch-stream-user-id s))228
(assert-equal "" (twitch-stream-user-name s))229
(assert-equal 0 (twitch-stream-viewer-count s)))))231
;; ---------------------------------------------------------------232
;; User parsing tests233
;; ---------------------------------------------------------------235
(test-group "user parsing"237
(test "parse full user resource"238
(let ((u (parse-user user-resource-json)))239
(assert-true (twitch-user? u))240
(assert-equal "141981764" (twitch-user-id u))241
(assert-equal "twitchdev" (twitch-user-login u))242
(assert-equal "TwitchDev" (twitch-user-display-name u))243
(assert-equal "partner" (twitch-user-broadcaster-type u))244
(assert-equal "Supporting devs" (twitch-user-description u))245
(assert-equal "2016-12-14T20:32:28Z" (twitch-user-created-at u))))247
(test "parse minimal user resource"248
(let ((u (parse-user user-minimal-json)))249
(assert-equal "54321" (twitch-user-id u))250
(assert-equal "testuser" (twitch-user-login u))251
(assert-equal "" (twitch-user-display-name u))252
(assert-equal #f (twitch-user-created-at u)))))254
;; ---------------------------------------------------------------255
;; URL encoding tests256
;; ---------------------------------------------------------------258
(test-group "URL encoding"260
(test "encode simple string"261
(assert-equal "hello" (url-encode-value "hello")))263
(test "encode spaces"264
(assert-equal "hello+world" (url-encode-value "hello world")))266
(test "encode special characters"267
(assert-equal "foo%26bar" (url-encode-value "foo&bar")))269
(test "encode equals sign"270
(assert-equal "key%3Dvalue" (url-encode-value "key=value")))272
(test "preserve unreserved characters"273
(assert-equal "a-b_c.d~e" (url-encode-value "a-b_c.d~e"))))275
;; ---------------------------------------------------------------276
;; Query string building tests277
;; ---------------------------------------------------------------279
(test-group "query string building"281
(test "build simple query string"282
(assert-equal "?broadcaster_id=12345"283
(build-query-string284
(list (cons "broadcaster_id" "12345")))))286
(test "build multi-param query string"287
(assert-equal "?part=snippet&id=abc123"288
(build-query-string289
(list (cons "part" "snippet")290
(cons "id" "abc123")))))292
(test "omit false values"293
(assert-equal "?broadcaster_id=12345"294
(build-query-string295
(list (cons "broadcaster_id" "12345")296
(cons "after" #f)))))298
(test "empty params"299
(assert-equal ""300
(build-query-string '())))302
(test "encode values in query string"303
(assert-equal "?q=hello+world"304
(build-query-string305
(list (cons "q" "hello world"))))))307
;; ---------------------------------------------------------------308
;; Pagination parsing tests309
;; ---------------------------------------------------------------311
(test-group "pagination parsing"313
(test "parse pagination with cursor"314
(let ((data #{ pagination: #{ cursor: "eyJiI123" } }))315
(assert-equal "eyJiI123" (parse-pagination data))))317
(test "parse pagination without cursor"318
(let ((data #{ pagination: #{} }))319
(assert-equal #f (parse-pagination data))))321
(test "parse pagination with missing pagination key"322
(let ((data #{}))323
(assert-equal #f (parse-pagination data)))))325
(run-tests)