Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store *noir-session* managed keys in :noir map inside :session. #110

Merged
merged 2 commits into from
Jun 6, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/noir/session.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
66 changes: 66 additions & 0 deletions test/noir/test/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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)))))