AtlatestRepositorysigil-web

sigil-web / tree / testtest-routes.sgl

1(import (sigil test)
2 (sigil web routes)
3 (sigil http request)
4 (sigil http response))
5
6;; ============================================================
7;; Test Helpers
8;; ============================================================
9
10(define (make-test-request method path)
11 (http-request method: method path: path headers: #{} body: #f))
13(define (ok-handler request)
14 (http-response status: 200 body: "ok"))
16(define (echo-path-handler request)
17 (http-response status: 200 body: (http-request-path request)))
19;; ============================================================
20;; route record
21;; ============================================================
23(test-group "route record"
24 (test "constructor and accessors"
25 (let ((r (route method: 'GET pattern: "/foo" handler: ok-handler)))
26 (assert-equal 'GET (route-method r))
27 (assert-equal "/foo" (route-pattern r))
28 (assert-equal ok-handler (route-handler r))))
30 (test "route with ANY method"
31 (let ((r (route method: 'ANY pattern: "/*path" handler: ok-handler)))
32 (assert-equal 'ANY (route-method r)))))
34;; ============================================================
35;; router - literal paths
36;; ============================================================
38(test-group "router - literal paths"
39 (test "exact match"
40 (let* ((app (router (route method: GET pattern: "/" handler: ok-handler)))
41 (res (app (make-test-request 'GET "/"))))
42 (assert-true (http-response? res))
43 (assert-equal 200 (http-response-status res))))
45 (test "no match returns #f"
46 (let* ((app (router (route method: GET pattern: "/foo" handler: ok-handler)))
47 (res (app (make-test-request 'GET "/bar"))))
48 (assert-false res)))
50 (test "multi-segment path"
51 (let* ((app (router (route method: GET pattern: "/api/users" handler: ok-handler)))
52 (res (app (make-test-request 'GET "/api/users"))))
53 (assert-true (http-response? res))
54 (assert-equal 200 (http-response-status res))))
56 (test "method mismatch"
57 (let* ((app (router (route method: GET pattern: "/" handler: ok-handler)))
58 (res (app (make-test-request 'POST "/"))))
59 (assert-false res)))
61 (test "ANY matches all methods"
62 (let ((app (router (route method: ANY pattern: "/any" handler: ok-handler))))
63 (assert-true (http-response? (app (make-test-request 'GET "/any"))))
64 (assert-true (http-response? (app (make-test-request 'POST "/any"))))
65 (assert-true (http-response? (app (make-test-request 'DELETE "/any")))))))
67;; ============================================================
68;; router - named parameters
69;; ============================================================
71(test-group "router - named parameters"
72 (test "single :id parameter"
73 (let* ((handler (lambda (req)
74 (http-response status: 200
75 body: (path-param req "id"))))
76 (app (router (route method: GET pattern: "/users/:id" handler: handler)))
77 (res (app (make-test-request 'GET "/users/42"))))
78 (assert-true (http-response? res))
79 (assert-equal "42" (http-response-body res))))
81 (test "multiple parameters"
82 (let* ((handler (lambda (req)
83 (http-response status: 200
84 body: (string-append
85 (path-param req "uid") ":"
86 (path-param req "pid")))))
87 (app (router (route method: GET pattern: "/users/:uid/posts/:pid" handler: handler)))
88 (res (app (make-test-request 'GET "/users/alice/posts/99"))))
89 (assert-equal "alice:99" (http-response-body res))))
91 (test "path-params returns full alist"
92 (let* ((handler (lambda (req)
93 (let ((params (path-params req)))
94 (http-response status: 200
95 body: (number->string (length params))))))
96 (app (router (route method: GET pattern: "/a/:x/b/:y" handler: handler)))
97 (res (app (make-test-request 'GET "/a/1/b/2"))))
98 (assert-equal "2" (http-response-body res))))
100 (test "path-param returns #f for missing param"
101 (let* ((handler (lambda (req)
102 (http-response status: 200
103 body: (if (path-param req "missing") "found" "not-found"))))
104 (app (router (route method: GET pattern: "/x/:id" handler: handler)))
105 (res (app (make-test-request 'GET "/x/1"))))
106 (assert-equal "not-found" (http-response-body res)))))
108;; ============================================================
109;; router - splat parameters
110;; ============================================================
112(test-group "router - splat parameters"
113 (test "*path captures rest of path"
114 (let* ((handler (lambda (req)
115 (http-response status: 200
116 body: (path-param req "path"))))
117 (app (router (route method: GET pattern: "/static/*path" handler: handler)))
118 (res (app (make-test-request 'GET "/static/css/style.css"))))
119 (assert-equal "css/style.css" (http-response-body res))))
121 (test "splat captures single segment"
122 (let* ((handler (lambda (req)
123 (http-response status: 200
124 body: (path-param req "file"))))
125 (app (router (route method: GET pattern: "/files/*file" handler: handler)))
126 (res (app (make-test-request 'GET "/files/readme.txt"))))
127 (assert-equal "readme.txt" (http-response-body res))))
129 (test "splat captures empty rest"
130 (let* ((handler (lambda (req)
131 (http-response status: 200
132 body: (path-param req "rest"))))
133 (app (router (route method: GET pattern: "/api/*rest" handler: handler)))
134 (res (app (make-test-request 'GET "/api/"))))
135 (assert-equal "" (http-response-body res)))))
137;; ============================================================
138;; router - first match wins
139;; ============================================================
141(test-group "router - first match wins"
142 (test "first matching route wins"
143 (let* ((handler1 (lambda (req) (http-response status: 200 body: "first")))
144 (handler2 (lambda (req) (http-response status: 200 body: "second")))
145 (app (router (route method: GET pattern: "/x" handler: handler1)
146 (route method: GET pattern: "/x" handler: handler2)))
147 (res (app (make-test-request 'GET "/x"))))
148 (assert-equal "first" (http-response-body res))))
150 (test "method differentiation"
151 (let* ((get-handler (lambda (req) (http-response status: 200 body: "get")))
152 (post-handler (lambda (req) (http-response status: 200 body: "post")))
153 (app (router (route method: GET pattern: "/x" handler: get-handler)
154 (route method: POST pattern: "/x" handler: post-handler)))
155 (get-res (app (make-test-request 'GET "/x")))
156 (post-res (app (make-test-request 'POST "/x"))))
157 (assert-equal "get" (http-response-body get-res))
158 (assert-equal "post" (http-response-body post-res)))))
160;; ============================================================
161;; routes combinator
162;; ============================================================
164(test-group "routes combinator"
165 (test "tries handlers in order, returns first non-#f"
166 (let* ((h1 (lambda (req) #f))
167 (h2 (lambda (req) (http-response status: 200 body: "h2")))
168 (h3 (lambda (req) (http-response status: 200 body: "h3")))
169 (app (routes h1 h2 h3))
170 (res (app (make-test-request 'GET "/"))))
171 (assert-equal "h2" (http-response-body res))))
173 (test "all #f returns #f"
174 (let* ((h1 (lambda (req) #f))
175 (h2 (lambda (req) #f))
176 (app (routes h1 h2))
177 (res (app (make-test-request 'GET "/"))))
178 (assert-false res)))
180 (test "first handler succeeds"
181 (let* ((h1 (lambda (req) (http-response status: 200 body: "first")))
182 (h2 (lambda (req) (http-response status: 200 body: "second")))
183 (app (routes h1 h2))
184 (res (app (make-test-request 'GET "/"))))
185 (assert-equal "first" (http-response-body res)))))
187(run-tests)