Permalink
Browse files

Merge pull request #110 from kenrestivo/session_fix

Store *noir-session* managed keys in :noir map inside :session.
  • Loading branch information...
2 parents 3e00cd5 + cda8f44 commit 6e71b333d1c4e01f79f71a9e7c9b549d0d3434de @Raynes Raynes committed Jun 6, 2012
Showing with 81 additions and 2 deletions.
  1. +15 −2 src/noir/session.clj
  2. +66 −0 test/noir/test/core.clj
View
@@ -50,11 +50,24 @@
cur)))
(defn noir-session [handler]
+ "Store noir session keys in a :noir map, because other middleware that
+ expects pure functions may delete keys, and simply merging won't work.
+ Ring takes (not (contains? response :session) to mean: don't update session.
+ Ring takes (nil? (:session resonse) to mean: delete the session.
+ Because noir-session mutates :session, it needs to duplicate ring/wrap-session
+ functionality to handle these cases."
(fn [request]
- (binding [*noir-session* (atom (:session request))]
+ (binding [*noir-session* (atom (get-in request [:session :noir] {}))]
(remove! :_flash)
(when-let [resp (handler request)]
- (assoc resp :session (merge @*noir-session* (:session resp)))))))
+ (if (= (get-in request [:session :noir] {}) @*noir-session*)
+ resp
+ (if (contains? resp :session)
+ (if (nil? (:session resp))
+ resp
+ (assoc-in resp [:session :noir] @*noir-session*))
+ (assoc resp :session (assoc (:session request) :noir @*noir-session*))))))))
+
(defn assoc-if [m k v]
(if (not (nil? v))
View
@@ -297,3 +297,69 @@
(deftest different-header
(-> (send-request "/different/status")
(has-status 201)))
+
+
+(deftest session
+ (with-noir
+ (session/put! :noir3 "woo")
+ (is (= "woo" (session/get :noir3)))
+ (is (nil? (session/get :noir4)))
+ (is (= "noir" (session/get :noir4 "noir")))))
+
+;;; regresssion tests, assure noir-session works with middleware like friend
+;;; which expects ring requests/responses to be pure functions
+
+(deftest noir-session
+ (let [base-map {:uri "/foo" :request-method :get }]
+ ;; put session value in
+ (is (= "bar" (get-in ((session/noir-session
+ #(assoc-in % [:session :foo] "bar"))
+ base-map)
+ [:session :foo])))
+ (let [base-map (assoc base-map :session {:foo "bar"})]
+ ;; pass session value through
+ (is (= "bar" (get-in ((session/noir-session identity)
+ base-map)
+ [:session :foo])))
+ ;; change session value
+ (is (= "baz" (get-in ((session/noir-session
+ #(assoc-in % [:session :foo] "baz"))
+ base-map)
+ [:session :foo])))
+ ;; dissoc session value
+ (is (not (contains? (:session
+ ((session/noir-session
+ #(assoc % :session (dissoc (:session %) :foo)))
+ base-map))
+ :foo))))
+ ;; dissocing one key doesn't affect any others
+ (let [base-map (assoc base-map :session {:foo "bar" :quuz "auugh"})
+ part-dissoc (:session
+ ((session/noir-session
+ #(assoc % :session (dissoc (:session %) :foo)))
+ base-map))]
+ (is (not (contains? part-dissoc :foo)))
+ (is (= "auugh" (:quuz part-dissoc)))
+ ;; changing one key doesn't affect any others
+ (let [part-change (:session
+ ((session/noir-session
+ #(assoc-in % [:session :foo] "baz"))
+ base-map))]
+ (is (= "baz" (:foo part-change)))
+ (is (= "auugh" (:quuz part-change)))))
+ ;; delete whole session.
+ ;; ring takes nil to mean delete session, so it must get passed through
+ (is (nil? (:session ((session/noir-session
+ #(assoc % :session nil))
+ base-map))))
+ ;; make sure the whole session goes away and stays away if deleted
+ (is (not (contains? ((session/noir-session
+ #(dissoc % :session))
+ base-map)
+ :session)))))
+
+
+
+
+
+

0 comments on commit 6e71b33

Please sign in to comment.