Commit98927edbRecorded15 Feb 2026Repositorysigil-jwt
test: Add JWT encode/decode/expiration tests for sigil-jwt package
Message
Tests jwt-encode structure, roundtrip encode/decode with claim recovery, wrong secret rejection, malformed token handling, expired/valid token expiration, and jwt-decode-unsafe.
Changed
test/test-jwt.sgl | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)Diff
test/test-jwt.sgladded
@@ -0,0 +1,79 @@
+1
(import (sigil test)+2
(sigil jwt)+3
(sigil time))+4
+5
;; ============================================================+6
;; jwt-encode+7
;; ============================================================+8
+9
(test-group "jwt-encode"+10
(test "produces 3 dot-separated parts"+11
(let ((token (jwt-encode '((sub . "user1")) "secret")))+12
(assert-true (string? token))+13
;; Count dots+14
(let ((parts (let loop ((s token) (parts '()) (current ""))+15
(if (= (string-length s) 0)+16
(reverse (cons current parts))+17
(if (char=? (string-ref s 0) #\.)+18
(loop (substring s 1 (string-length s))+19
(cons current parts)+20
"")+21
(loop (substring s 1 (string-length s))+22
parts+23
(string-append current (string (string-ref s 0)))))))))+24
(assert-equal 3 (length parts))))))+25
+26
;; ============================================================+27
;; jwt-decode roundtrip+28
;; ============================================================+29
+30
(test-group "jwt-decode"+31
(test "roundtrip encode/decode recovers claims"+32
(let* ((claims '((sub . "user123") (role . "admin")))+33
(token (jwt-encode claims "my-secret"))+34
(decoded (jwt-decode token "my-secret")))+35
(assert-true (dict? decoded))+36
(assert-equal "user123" (dict-ref decoded sub:))+37
(assert-equal "admin" (dict-ref decoded role:))))+38
+39
(test "wrong secret returns #f"+40
(let* ((token (jwt-encode '((sub . "user")) "correct-secret"))+41
(decoded (jwt-decode token "wrong-secret")))+42
(assert-false decoded)))+43
+44
(test "malformed token returns #f"+45
(assert-false (jwt-decode "not.a.valid-token" "secret"))+46
(assert-false (jwt-decode "onlyonepart" "secret"))))+47
+48
;; ============================================================+49
;; Expiration+50
;; ============================================================+51
+52
(test-group "expiration"+53
(test "expired token rejected"+54
(let* ((claims (list (cons 'sub "user")+55
(cons 'exp (- (floor (current-second)) 3600))))+56
(token (jwt-encode claims "secret"))+57
(decoded (jwt-decode token "secret")))+58
(assert-false decoded)))+59
+60
(test "valid future token accepted"+61
(let* ((claims (list (cons 'sub "user")+62
(cons 'exp (+ (floor (current-second)) 3600))))+63
(token (jwt-encode claims "secret"))+64
(decoded (jwt-decode token "secret")))+65
(assert-true (dict? decoded))+66
(assert-equal "user" (dict-ref decoded sub:)))))+67
+68
;; ============================================================+69
;; jwt-decode-unsafe+70
;; ============================================================+71
+72
(test-group "jwt-decode-unsafe"+73
(test "decodes without verifying signature"+74
(let* ((token (jwt-encode '((sub . "peek")) "secret"))+75
(decoded (jwt-decode-unsafe token)))+76
(assert-true (dict? decoded))+77
(assert-equal "peek" (dict-ref decoded sub:)))))+78
+79
(run-tests)