Fix cljs-tests?

This commit is contained in:
Tommi Reiman 2017-09-08 09:42:37 +03:00
parent 1d74dd31b7
commit 2c00b753c3
4 changed files with 35 additions and 30 deletions

View file

@ -147,7 +147,7 @@ Only a partial match. Let's provide the path-parameters:
There is also a exception throwing version: There is also a exception throwing version:
``` ```clj
(reitit/match-by-name! router ::user) (reitit/match-by-name! router ::user)
; ExceptionInfo missing path-params for route /api/user/:id: #{:id} ; ExceptionInfo missing path-params for route /api/user/:id: #{:id}
``` ```
@ -266,7 +266,7 @@ The expanded routes:
```clj ```clj
(-> app (ring/get-router) (reitit/routes)) (-> app (ring/get-router) (reitit/routes))
; [["/ping" ; [["/ping"
; {:handler #object[user$handler 0x5c312d6f "user$handler@5c312d6f"]} ; {:handler #object[...]}
; #Methods{:any #Endpoint{:meta {:handler #object[...]}, ; #Methods{:any #Endpoint{:meta {:handler #object[...]},
; :handler #object[...], ; :handler #object[...],
; :middleware []}}]] ; :middleware []}}]]
@ -307,10 +307,10 @@ Reverse routing:
Middleware can be added with a `:middleware` key, with a vector value of the following: Middleware can be added with a `:middleware` key, with a vector value of the following:
1. ring middleware function (`handler -> request -> response`) 1. ring middleware function `handler -> request -> response`
2. vector of middleware function (`handler ?args -> request -> response`) and optinally it's args. 2. vector of middleware function `handler ?args -> request -> response` and optinally it's args.
Let's define some middleware and a handler: A middleware and a handler:
```clj ```clj
(defn wrap [handler id] (defn wrap [handler id]
@ -357,7 +357,7 @@ Reitit supports first-class data-driven middleware via `reitit.middleware/Middle
| `:wrap` | The actual middleware function of `handler args? => request => response` | `:wrap` | The actual middleware function of `handler args? => request => response`
| `:gen` | Middleware compile function, see [compiling middleware](#compiling-middleware). | `:gen` | Middleware compile function, see [compiling middleware](#compiling-middleware).
Behind the scenes, when routes are compiled, all middleware are first expanded into `Middleware` and stored as such in compilation results to be used for api-docs etc. For actual request processing, they are unwrapped into normal middleware functions producing zero runtime performance penalty. Thanks to the `reitit.middleware/IntoMiddleware` protocol, plain clojure(script) maps can also be used. When routes are compiled, all middleware are expanded (and optionally compiled) into `Middleware` and stored in compilation results for later use (api-docs etc). For actual request processing, they are unwrapped into normal middleware functions producing zero runtime performance penalty. Middleware expansion is backed by `reitit.middleware/IntoMiddleware` protocol, enabling plain clojure(script) maps to be used.
A Record: A Record:
@ -384,13 +384,13 @@ As plain map:
### Async Ring ### Async Ring
All built-in middleware provide both the 2 and 3-arity, so they work with [Async Ring](https://www.booleanknot.com/blog/2016/07/15/asynchronous-ring.html) too. All built-in middleware provide both 2 and 3-arity and are compiled for both Clojure & ClojureScript, so they work with [Async Ring](https://www.booleanknot.com/blog/2016/07/15/asynchronous-ring.html) and [Node.js](https://nodejs.org) too.
### Meta-data based extensions ### Meta-data based extensions
`ring-handler` injects the `Match` into a request and it can be extracted at runtime with `reitit.ring/get-match`. This can be used to build dynamic extensions to the system. `ring-handler` injects the `Match` into a request and it can be extracted at runtime with `reitit.ring/get-match`. This can be used to build dynamic extensions to the system.
A middleware to guard routes based on user roles: Example middleware to guard routes based on user roles:
```clj ```clj
(require '[clojure.set :as set]) (require '[clojure.set :as set])
@ -540,7 +540,7 @@ Still, we can do better. As we know the exact route that interceptor/middleware
To do this we use [middleware records](#middleware-records) `:gen` hook instead of the normal `:wrap`. `:gen` expects a function of `route-meta router-opts => wrap`. Middleware can also return `nil`, which effective unmounts the middleware. Why mount a `wrap-enforce-roles` middleware for a route if there are no roles required for it? To do this we use [middleware records](#middleware-records) `:gen` hook instead of the normal `:wrap`. `:gen` expects a function of `route-meta router-opts => wrap`. Middleware can also return `nil`, which effective unmounts the middleware. Why mount a `wrap-enforce-roles` middleware for a route if there are no roles required for it?
To demonstrate the two approaches, below are response coercion middleware written as normal ring middleware function and as middleware record with `:gen`. These are the actual codes are from `reitit.coercion`: To demonstrate the two approaches, below are response coercion middleware written as normal ring middleware function and as middleware record with `:gen`. These are the actual codes are from [`reitit.coercion`](https://github.com/metosin/reitit/blob/master/src/reitit/coercion.cljc):
### Naive ### Naive

View file

@ -33,7 +33,7 @@
(s/def ::y (s/and (s/conformer #(if (string? %) (Long/parseLong %) %) identity) int?)) (s/def ::y (s/and (s/conformer #(if (string? %) (Long/parseLong %) %) identity) int?))
(s/def ::k (s/keys :req-un [::x ::y])) (s/def ::k (s/keys :req-un [::x ::y]))
(let [spec (spec/specify {:x int?, :y int?} ::jeah) (let [spec (spec/into-spec {:x int?, :y int?} ::jeah)
coercers (#'coercion/request-coercers spec/coercion {:body spec}) coercers (#'coercion/request-coercers spec/coercion {:body spec})
params {:x "1", :y "2"} params {:x "1", :y "2"}
request {:body-params {:x "1", :y "2"}}] request {:body-params {:x "1", :y "2"}}]

View file

@ -23,31 +23,32 @@
(def default-conforming (def default-conforming
::default) ::default)
(defprotocol Specify (defprotocol IntoSpec
(specify [this name])) (into-spec [this name]))
(extend-protocol Specify (extend-protocol IntoSpec
#?(:clj clojure.lang.PersistentArrayMap #?(:clj clojure.lang.PersistentArrayMap
:cljs cljs.core.PersistentArrayMap) :cljs cljs.core.PersistentArrayMap)
(specify [this name] (into-spec [this name]
(ds/spec name this)) (ds/spec name this))
#?(:clj clojure.lang.PersistentHashMap #?(:clj clojure.lang.PersistentHashMap
:cljs cljs.core.PersistentHashMap) :cljs cljs.core.PersistentHashMap)
(specify [this name] (into-spec [this name]
(ds/spec name this)) (ds/spec name this))
Spec Spec
(specify [this _] this) (into-spec [this _] this)
Object #?(:clj Object
(specify [this _] :cljs default)
(into-spec [this _]
(st/create-spec {:spec this}))) (st/create-spec {:spec this})))
;; TODO: proper name! ;; TODO: proper name!
(def memoized-specify (def memoized-into-spec
(memoize #(specify %1 (gensym "spec")))) (memoize #(into-spec %1 (gensym "spec"))))
(defmulti coerce-response? identity :default ::default) (defmulti coerce-response? identity :default ::default)
(defmethod coerce-response? ::default [_] true) (defmethod coerce-response? ::default [_] true)
@ -58,7 +59,7 @@
(get-name [_] name) (get-name [_] name)
(compile [_ model _] (compile [_ model _]
(memoized-specify model)) (memoized-into-spec model))
(get-apidocs [_ _ {:keys [parameters responses] :as info}] (get-apidocs [_ _ {:keys [parameters responses] :as info}]
(cond-> (dissoc info :parameters :responses) (cond-> (dissoc info :parameters :responses)
@ -67,13 +68,13 @@
(into (into
(empty parameters) (empty parameters)
(for [[k v] parameters] (for [[k v] parameters]
[k memoized-specify]))) [k memoized-into-spec])))
responses (assoc responses (assoc
::swagger/responses ::swagger/responses
(into (into
(empty responses) (empty responses)
(for [[k response] responses] (for [[k response] responses]
[k (update response :schema memoized-specify)]))))) [k (update response :schema memoized-into-spec)])))))
(make-open [_ spec] spec) (make-open [_ spec] spec)
@ -81,7 +82,7 @@
(update error :spec (comp str s/form))) (update error :spec (comp str s/form)))
(request-coercer [_ type spec] (request-coercer [_ type spec]
(let [spec (memoized-specify spec) (let [spec (memoized-into-spec spec)
{:keys [formats default]} (conforming type)] {:keys [formats default]} (conforming type)]
(fn [value format] (fn [value format]
(if-let [conforming (or (get formats format) default)] (if-let [conforming (or (get formats format) default)]
@ -101,9 +102,7 @@
(def default-options (def default-options
{:coerce-response? coerce-response? {:coerce-response? coerce-response?
:conforming {:body {:default default-conforming :conforming {:body {:default default-conforming
:formats {"application/json" json-conforming :formats {"application/json" json-conforming}}
"application/msgpack" json-conforming
"application/x-yaml" json-conforming}}
:string {:default string-conforming} :string {:default string-conforming}
:response {:default default-conforming}}}) :response {:default default-conforming}}})

View file

@ -1,9 +1,15 @@
(ns reitit.doo-runner (ns reitit.doo-runner
(:require [doo.runner :refer-macros [doo-tests]] (:require [doo.runner :refer-macros [doo-tests]]
reitit.coercion-test
reitit.core-test reitit.core-test
reitit.ring-test)) reitit.middleware-test
reitit.ring-test
reitit.spec-test))
(enable-console-print!) (enable-console-print!)
(doo-tests 'reitit.core-test (doo-tests 'reitit.coercion-test
'reitit.ring-test) 'reitit.core-test
'reitit.middleware-test
'reitit.ring-test
'reitit.spec-test)