mirror of
https://github.com/metosin/reitit.git
synced 2025-12-17 00:11:11 +00:00
doesn't work properly with spec
This commit is contained in:
parent
ce06214014
commit
9ac713f0e5
3 changed files with 54 additions and 13 deletions
|
|
@ -15,7 +15,7 @@ We use [Break Versioning][breakver]. The version numbers follow a `<major>.<mino
|
||||||
## UNRELEASED
|
## UNRELEASED
|
||||||
|
|
||||||
**BREAKING**: `compile-request-coercers` returns a map with `:data` and `:coerce` instead of plain `:coerce` function
|
**BREAKING**: `compile-request-coercers` returns a map with `:data` and `:coerce` instead of plain `:coerce` function
|
||||||
**BREAKING**: Parameter and Response schemas are acculated into vector in route data - to be merged properly into compiled result, fixes [#422](https://github.com/metosin/reitit/issues/422) - works will all of `Malli`, `Schema` and `Spec`.
|
**BREAKING**: Parameter and Response schemas are acculated into vector in route data - to be merged properly into compiled result, fixes [#422](https://github.com/metosin/reitit/issues/422) - merging multiple schemas together works with `Malli` and `Schema`, partially with `data-spec` but not with `spec`.
|
||||||
|
|
||||||
```clojure
|
```clojure
|
||||||
[metosin/schema-tools "0.13.1"] is available but we use "0.13.0"
|
[metosin/schema-tools "0.13.1"] is available but we use "0.13.0"
|
||||||
|
|
|
||||||
|
|
@ -143,10 +143,8 @@
|
||||||
(= (count model) 1) (first model)
|
(= (count model) 1) (first model)
|
||||||
;; here be dragons, best effort
|
;; here be dragons, best effort
|
||||||
(every? map? model) (apply mm/meta-merge model)
|
(every? map? model) (apply mm/meta-merge model)
|
||||||
;; not sure if this is what we want
|
|
||||||
(every? s/spec? model) (reduce (fn [acc s] (st/merge acc s)) model)
|
|
||||||
;; fail fast
|
;; fail fast
|
||||||
:else (ex/fail! ::model-error {:message "Can't merge nested data-specs & specs together", :spec model}))
|
:else (ex/fail! ::model-error {:message "Can't merge nested clojure specs", :spec model}))
|
||||||
name))
|
name))
|
||||||
(-open-model [_ spec] spec)
|
(-open-model [_ spec] spec)
|
||||||
(-encode-error [_ error]
|
(-encode-error [_ error]
|
||||||
|
|
|
||||||
|
|
@ -7,32 +7,52 @@
|
||||||
[reitit.coercion.spec]
|
[reitit.coercion.spec]
|
||||||
[reitit.core :as r]
|
[reitit.core :as r]
|
||||||
[schema.core :as s]
|
[schema.core :as s]
|
||||||
|
[clojure.spec.alpha :as cs]
|
||||||
[spec-tools.data-spec :as ds])
|
[spec-tools.data-spec :as ds])
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(:import (clojure.lang ExceptionInfo))))
|
(:import (clojure.lang ExceptionInfo))))
|
||||||
|
|
||||||
|
(cs/def ::number int?)
|
||||||
|
(cs/def ::keyword keyword?)
|
||||||
|
(cs/def ::int int?)
|
||||||
|
(cs/def ::ints (cs/coll-of int? :kind vector))
|
||||||
|
(cs/def ::map (cs/map-of int? int?))
|
||||||
|
|
||||||
(deftest coercion-test
|
(deftest coercion-test
|
||||||
(let [r (r/router
|
(let [r (r/router
|
||||||
[["/schema" {:coercion reitit.coercion.schema/coercion}
|
[["/schema" {:coercion reitit.coercion.schema/coercion}
|
||||||
["/:number" {:parameters {:path {:number s/Int}}}
|
["/:number" {:parameters {:path {:number s/Int}}}
|
||||||
["/:keyword" {:parameters {:path {:keyword s/Keyword}
|
["/:keyword" {:parameters {:path {:keyword s/Keyword}
|
||||||
:query (s/maybe {:int s/Int, :ints [s/Int], :map {s/Int s/Int}})}}]]]
|
:query (s/maybe {:int s/Int, :ints [s/Int], :map {s/Int s/Int}})}}]]]
|
||||||
|
|
||||||
["/malli" {:coercion reitit.coercion.malli/coercion}
|
["/malli" {:coercion reitit.coercion.malli/coercion}
|
||||||
["/:number" {:parameters {:path [:map [:number int?]]}}
|
["/:number" {:parameters {:path [:map [:number int?]]}}
|
||||||
["/:keyword" {:parameters {:path [:map [:keyword keyword?]]
|
["/:keyword" {:parameters {:path [:map [:keyword keyword?]]
|
||||||
:query [:maybe [:map [:int int?]
|
:query [:maybe [:map [:int int?]
|
||||||
[:ints [:vector int?]]
|
[:ints [:vector int?]]
|
||||||
[:map [:map-of int? int?]]]]}}]]]
|
[:map [:map-of int? int?]]]]}}]]]
|
||||||
|
|
||||||
["/malli-lite" {:coercion reitit.coercion.malli/coercion}
|
["/malli-lite" {:coercion reitit.coercion.malli/coercion}
|
||||||
["/:number" {:parameters {:path {:number int?}}}
|
["/:number" {:parameters {:path {:number int?}}}
|
||||||
["/:keyword" {:parameters {:path {:keyword keyword?}
|
["/:keyword" {:parameters {:path {:keyword keyword?}
|
||||||
:query (l/maybe {:int int?
|
:query (l/maybe {:int int?
|
||||||
:ints (l/vector int?)
|
:ints (l/vector int?)
|
||||||
:map (l/map-of int? int?)})}}]]]
|
:map (l/map-of int? int?)})}}]]]
|
||||||
["/spec" {:coercion reitit.coercion.spec/coercion}
|
|
||||||
|
#_["/spec" {:coercion reitit.coercion.spec/coercion}
|
||||||
|
["/:number" {:parameters {:path (cs/keys :req-un [::number])}}
|
||||||
|
["/:keyword" {:parameters {:path (cs/keys :req-un [::keyword])
|
||||||
|
:query (cs/nilable (cs/keys :req-un [::int ::ints ::map]))}}]]]
|
||||||
|
|
||||||
|
["/spec-shallow" {:coercion reitit.coercion.spec/coercion}
|
||||||
|
["/:number/:keyword" {:parameters {:path (cs/keys :req-un [::number ::keyword])
|
||||||
|
:query (cs/nilable (cs/keys :req-un [::int ::ints ::map]))}}]]
|
||||||
|
|
||||||
|
["/data-spec" {:coercion reitit.coercion.spec/coercion}
|
||||||
["/:number" {:parameters {:path {:number int?}}}
|
["/:number" {:parameters {:path {:number int?}}}
|
||||||
["/:keyword" {:parameters {:path {:keyword keyword?}
|
["/:keyword" {:parameters {:path {:keyword keyword?}
|
||||||
:query (ds/maybe {:int int?, :ints [int?], :map {int? int?}})}}]]]
|
:query (ds/maybe {:int int?, :ints [int?], :map {int? int?}})}}]]]
|
||||||
|
|
||||||
["/none"
|
["/none"
|
||||||
["/:number" {:parameters {:path {:number int?}}}
|
["/:number" {:parameters {:path {:number int?}}}
|
||||||
["/:keyword" {:parameters {:path {:keyword keyword?}}}]]]]
|
["/:keyword" {:parameters {:path {:keyword keyword?}}}]]]]
|
||||||
|
|
@ -74,19 +94,42 @@
|
||||||
(let [m (r/match-by-path r "/malli-lite/kikka/abba")]
|
(let [m (r/match-by-path r "/malli-lite/kikka/abba")]
|
||||||
(is (thrown? ExceptionInfo (coercion/coerce! m))))))
|
(is (thrown? ExceptionInfo (coercion/coerce! m))))))
|
||||||
|
|
||||||
;; TODO: :map-of fails with string-keys
|
#_(testing "spec-coercion"
|
||||||
(testing "spec-coercion"
|
(testing "fails"
|
||||||
(testing "succeeds"
|
|
||||||
(let [m (r/match-by-path r "/spec/1/abba")]
|
(let [m (r/match-by-path r "/spec/1/abba")]
|
||||||
(is (= {:path {:keyword :abba, :number 1}, :query nil}
|
(is (thrown? ExceptionInfo (coercion/coerce! m))))
|
||||||
(coercion/coerce! m))))
|
(let [m (r/match-by-path r "/spec/1/abba")]
|
||||||
(let [m (r/match-by-path r "/schema/1/abba")]
|
(is (thrown? ExceptionInfo (coercion/coerce! m)))))
|
||||||
(is (= {:path {:keyword :abba, :number 1}, :query {:int 10, :ints [1, 2, 3], :map {1 1, #_#_2 2}}}
|
|
||||||
(coercion/coerce! (assoc m :query-params {"int" "10", "ints" ["1" "2" "3"], "map" {:1 "1"}, #_#_"2" "2"}))))))
|
|
||||||
(testing "throws with invalid input"
|
(testing "throws with invalid input"
|
||||||
(let [m (r/match-by-path r "/spec/kikka/abba")]
|
(let [m (r/match-by-path r "/spec/kikka/abba")]
|
||||||
(is (thrown? ExceptionInfo (coercion/coerce! m))))))
|
(is (thrown? ExceptionInfo (coercion/coerce! m))))))
|
||||||
|
|
||||||
|
(testing "spec-coercion (shallow)"
|
||||||
|
(testing "succeeds"
|
||||||
|
(let [m (r/match-by-path r "/spec-shallow/1/abba")]
|
||||||
|
(def MATCH m)
|
||||||
|
(is (= {:path {:keyword :abba, :number 1}, :query nil}
|
||||||
|
(coercion/coerce! m))))
|
||||||
|
(let [m (r/match-by-path r "/spec-shallow/1/abba")]
|
||||||
|
(is (= {:path {:keyword :abba, :number 1}, :query {:int 10, :ints [1, 2, 3], :map {1 1, #_#_2 2}}}
|
||||||
|
(coercion/coerce! (assoc m :query-params {"int" "10", "ints" ["1" "2" "3"], "map" {:1 "1"}, #_#_"2" "2"}))))))
|
||||||
|
(testing "throws with invalid input"
|
||||||
|
(let [m (r/match-by-path r "/spec-shallow/kikka/abba")]
|
||||||
|
(is (thrown? ExceptionInfo (coercion/coerce! m))))))
|
||||||
|
|
||||||
|
;; TODO: :map-of fails with string-keys
|
||||||
|
#_(testing "data-spec-coercion"
|
||||||
|
(testing "succeeds"
|
||||||
|
(let [m (r/match-by-path r "/data-spec/1/abba")]
|
||||||
|
(is (= {:path {:keyword :abba, :number 1}, :query nil}
|
||||||
|
(coercion/coerce! m))))
|
||||||
|
(let [m (r/match-by-path r "/data-spec/1/abba")]
|
||||||
|
(is (= {:path {:keyword :abba, :number 1}, :query {:int 10, :ints [1, 2, 3], :map {1 1, #_#_2 2}}}
|
||||||
|
(coercion/coerce! (assoc m :query-params {"int" "10", "ints" ["1" "2" "3"], "map" {:1 "1"}, #_#_"2" "2"}))))))
|
||||||
|
(testing "throws with invalid input"
|
||||||
|
(let [m (r/match-by-path r "/data-spec/kikka/abba")]
|
||||||
|
(is (thrown? ExceptionInfo (coercion/coerce! m))))))
|
||||||
|
|
||||||
(testing "no coercion defined"
|
(testing "no coercion defined"
|
||||||
(testing "doesn't coerce"
|
(testing "doesn't coerce"
|
||||||
(let [m (r/match-by-path r "/none/1/abba")]
|
(let [m (r/match-by-path r "/none/1/abba")]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue