Skip to content

Commit 184b300

Browse files
committed
Add server-side tests for the Ring handler
The test suite only covered eval round-trips through a real Jetty server via drawbridge.client-test. This adds direct Ring-level tests for the handler returned by ring-handler, covering method rejection, GET-with-op rejection, eval responses, session persistence, custom cookie names, and custom nREPL handlers.
1 parent 93f36b0 commit 184b300

1 file changed

Lines changed: 113 additions & 0 deletions

File tree

test/drawbridge/core_test.clj

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
(ns drawbridge.core-test
2+
(:require [clojure.string :as str]
3+
[clojure.test :refer [are deftest is testing]]
4+
[cheshire.core :as json]
5+
[drawbridge.core :as drawbridge]
6+
[nrepl.transport :as transport]
7+
[ring.middleware.keyword-params :refer [wrap-keyword-params]]
8+
[ring.middleware.nested-params :refer [wrap-nested-params]]
9+
[ring.middleware.params :refer [wrap-params]]))
10+
11+
(defn- make-handler
12+
[& opts]
13+
(-> (apply drawbridge/ring-handler opts)
14+
wrap-keyword-params
15+
wrap-nested-params
16+
wrap-params))
17+
18+
(defn- parse-body
19+
[body]
20+
(json/parse-string (apply str body) true))
21+
22+
(defn- encode-params [params]
23+
(str/join "&" (map (fn [[k v]]
24+
(str (name k) "=" (java.net.URLEncoder/encode (str v) "UTF-8")))
25+
params)))
26+
27+
(defn- request
28+
[method & [params headers]]
29+
(let [qs (when (seq params) (encode-params params))]
30+
(cond-> {:request-method method
31+
:uri "/repl"
32+
:headers (or headers {})}
33+
(and (= method :get) qs)
34+
(assoc :query-string qs)
35+
36+
(= method :post)
37+
(-> (assoc :body (java.io.ByteArrayInputStream.
38+
(.getBytes (or qs "") "UTF-8")))
39+
(assoc-in [:headers "content-type"] "application/x-www-form-urlencoded")))))
40+
41+
(defn- get-set-cookie [response]
42+
(let [v (get-in response [:headers "Set-Cookie"])]
43+
(cond
44+
(string? v) v
45+
(sequential? v) (str/join "; " v))))
46+
47+
(defn- extract-session-cookie [response cookie-name]
48+
(some->> (get-set-cookie response)
49+
(re-find (re-pattern (str cookie-name "=([^;]+)")))
50+
second))
51+
52+
(deftest method-rejection
53+
(let [handler (make-handler)]
54+
(testing "unsupported methods return 405 with illegal method error"
55+
(are [method] (let [resp (handler (request method))
56+
body (json/parse-string (:body resp) true)]
57+
(and (= 405 (:status resp))
58+
(= "Method Not Allowed" (:error body))
59+
(re-find #"Only GET and POST" (:reason body))))
60+
:put :delete :patch))
61+
62+
(testing "GET with an op parameter returns 405"
63+
(let [resp (handler (request :get {:op "eval" :code "(+ 1 2)"}))
64+
body (json/parse-string (:body resp) true)]
65+
(is (= 405 (:status resp)))
66+
(is (= "Method Not Allowed" (:error body)))
67+
(is (re-find #"POST request method" (:reason body)))))))
68+
69+
(deftest ring-handler-responses
70+
(testing "GET returns empty response array"
71+
(let [handler (make-handler)
72+
resp (handler (request :get))]
73+
(is (= 200 (:status resp)))
74+
(is (= [] (parse-body (:body resp))))))
75+
76+
(testing "POST eval returns result"
77+
(let [handler (make-handler :default-read-timeout 5000)
78+
resp (handler (request :post {:op "eval" :code "(+ 1 2)"}))
79+
messages (parse-body (:body resp))]
80+
(is (= 200 (:status resp)))
81+
(is (some #(= "3" (:value %)) messages)))))
82+
83+
(deftest session-handling
84+
(testing "session cookie is set and can be reused"
85+
(let [handler (make-handler :default-read-timeout 5000)
86+
cookie-name "drawbridge-session"
87+
resp1 (handler (request :post {:op "eval" :code "(+ 10 20)"}))
88+
cookie (extract-session-cookie resp1 cookie-name)]
89+
(is (some? cookie) "Session cookie should be set")
90+
(let [resp2 (handler (-> (request :get)
91+
(assoc-in [:headers "cookie"]
92+
(str cookie-name "=" cookie))))]
93+
(is (= 200 (:status resp2))))))
94+
95+
(testing "custom cookie name is used in Set-Cookie header"
96+
(let [handler (make-handler :cookie-name "my-session")
97+
resp (handler (request :get))
98+
set-cookie (get-set-cookie resp)]
99+
(is (some? set-cookie))
100+
(is (re-find #"my-session=" set-cookie)))))
101+
102+
(deftest custom-nrepl-handler
103+
(testing "responses come from the supplied handler"
104+
(let [marker "custom-handler-marker"
105+
custom-handler (fn [msg]
106+
(transport/send (:transport msg)
107+
{:status :done :value marker}))
108+
handler (make-handler :nrepl-handler custom-handler
109+
:default-read-timeout 5000)
110+
resp (handler (request :post {:op "eval" :code "ignored"}))
111+
messages (parse-body (:body resp))]
112+
(is (= 200 (:status resp)))
113+
(is (some #(= marker (:value %)) messages)))))

0 commit comments

Comments
 (0)