Skip to content

Commit

Permalink
Merge pull request #845 from opqdonut/fix/humanize
Browse files Browse the repository at this point in the history
fix: error paths for :multi schemas when value is not a map
  • Loading branch information
opqdonut authored Feb 8, 2023
2 parents c2bc49e + d5efc67 commit 4d739d9
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 10 deletions.
6 changes: 3 additions & 3 deletions src/malli/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -1513,12 +1513,12 @@
(let [find (finder (reduce-kv (fn [acc k s] (assoc acc k (-validator s))) {} @dispatch-map))]
(fn [x] (if-let [validator (find (dispatch x))] (validator x) false))))
(-explainer [this path]
(let [find (finder (reduce (fn [acc [k s]] (assoc acc k (-explainer s (conj path k)))) {} (-entries this)))
->path (if (keyword? dispatch) #(conj % dispatch) identity)]
(let [find (finder (reduce (fn [acc [k s]] (assoc acc k (-explainer s (conj path k)))) {} (-entries this)))]
(fn [x in acc]
(if-let [explainer (find (dispatch x))]
(explainer x in acc)
(conj acc (miu/-error (->path path) (->path in) this x ::invalid-dispatch-value))))))
(let [->path (if (and (map? x) (keyword? dispatch)) #(conj % dispatch) identity)]
(conj acc (miu/-error (->path path) (->path in) this x ::invalid-dispatch-value)))))))
(-parser [_]
(let [parse (fn [k s] (let [p (-parser s)] (fn [x] (miu/-map-valid #(miu/-tagged k %) (p x)))))
find (finder (reduce-kv (fn [acc k s] (assoc acc k (parse k s))) {} @dispatch-map))]
Expand Down
50 changes: 46 additions & 4 deletions test/malli/core_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@
(m/walk [:map {:registry {::age [:and int? [:> 18]]}} [:age ::age]]
(m/schema-walker identity)))))

(defrecord SomeRecord [])

(deftest validation-test

(testing "coercion"
Expand Down Expand Up @@ -1024,19 +1026,26 @@
[:human [:map [:type keyword?] [:name string?] [:address [:map [:country keyword?]]]]]]
valid1 {:type :sized, :size 10}
valid2 {:type :human :name "inkeri", :address {:country :PO}}
valid3 (map->SomeRecord {:type :sized, :size 10})
invalid1 {:type :sized, :size "size"}
invalid2 {:type :human :namez "inkeri"}
invalid3 {:type :worm}]
invalid3 {:type :worm}
invalid4 []
invalid5 "xxx"
invalid6 (map->SomeRecord {:type :record})]

(is (true? (m/validate schema valid1)))
(is (true? (m/validate schema valid2)))
(is (true? (m/validate schema valid3)))
(is (false? (m/validate schema invalid1)))
(is (false? (m/validate schema invalid2)))
(is (false? (m/validate schema invalid3)))
(is (false? (m/validate schema "not-a-map")))
(is (false? (m/validate schema invalid4)))
(is (false? (m/validate schema invalid5)))

(is (nil? (m/explain schema valid1)))
(is (nil? (m/explain schema valid2)))
(is (nil? (m/explain schema valid3)))

(is (results= {:schema schema,
:value {:type :sized, :size "size"},
Expand Down Expand Up @@ -1066,18 +1075,51 @@
:type :malli.core/invalid-dispatch-value}]}
(m/explain schema invalid3)))

(is (results= {:schema schema,
:value []
:errors [{:path []
:in []
:schema schema
:value []
:type :malli.core/invalid-dispatch-value}]}
(m/explain schema invalid4)))

(is (results= {:schema schema,
:value "xxx"
:errors [{:path []
:in []
:schema schema
:value "xxx"
:type :malli.core/invalid-dispatch-value}]}
(m/explain schema invalid5)))

(is (results= {:schema schema,
:value invalid6
:errors [{:path [:type]
:in [:type]
:schema schema
:value invalid6
:type :malli.core/invalid-dispatch-value}]}
(m/explain schema invalid6)))

(is (= (miu/-tagged :sized valid1) (m/parse schema valid1)))
(is (= (miu/-tagged :human valid2) (m/parse schema valid2)))
(is (= (miu/-tagged :sized valid3) (m/parse schema valid3)))
(is (= ::m/invalid (m/parse schema invalid1)))
(is (= ::m/invalid (m/parse schema invalid2)))
(is (= ::m/invalid (m/parse schema invalid3)))
(is (= ::m/invalid (m/parse schema "not-a-map")))
(is (= ::m/invalid (m/parse schema invalid4)))
(is (= ::m/invalid (m/parse schema invalid5)))
(is (= ::m/invalid (m/parse schema invalid6)))
(is (= valid1 (m/unparse schema (m/parse schema valid1))))
(is (= valid2 (m/unparse schema (m/parse schema valid2))))
(is (= valid3 (m/unparse schema (m/parse schema valid3))))
(is (= ::m/invalid (m/unparse schema invalid1)))
(is (= ::m/invalid (m/unparse schema invalid2)))
(is (= ::m/invalid (m/unparse schema invalid3)))
(is (= ::m/invalid (m/unparse schema "not-a-map")))
(is (= ::m/invalid (m/unparse schema invalid4)))
(is (= ::m/invalid (m/unparse schema invalid5)))
(is (= ::m/invalid (m/unparse schema invalid6)))

(is (= {:type :sized, :size 10}
(m/decode schema {:type "sized", :size "10"} mt/string-transformer)))
Expand Down
19 changes: 16 additions & 3 deletions test/malli/error_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,8 @@
(is (= ["should be an ifn"]
(me/humanize (m/explain ifn? 123)))))

(defrecord Horror [])

(deftest multi-error-test
(let [schema [:multi {:dispatch :type}
["plus" [:map [:value int?]]]
Expand All @@ -454,6 +456,19 @@
(-> schema
(m/explain {:type "minuz"})
(me/with-spell-checking)
(me/humanize)))))

(testing "explain works even when dispatch is a keyword but value is not a map"
(is (= ["invalid dispatch value"]
(-> (m/schema [:multi {:dispatch :x}
[:y [:map [:x :keyword]]]])
(m/explain [])
(me/humanize))))

(is (= {:x ["invalid dispatch value"]}
(-> (m/schema [:multi {:dispatch :x}
[:y [:map [:x :keyword]]]])
(m/explain (map->Horror {:foo :bar}))
(me/humanize))))))

(deftest explain-sequential
Expand Down Expand Up @@ -604,8 +619,6 @@
:f [1 2 3 4]})
(me/humanize)))))

(defrecord Horror [])

(deftest robust-humanize-form
(let [f (fn [s] [:fn {:error/message s} (constantly false)])
=> ::irrelevant]
Expand Down Expand Up @@ -651,7 +664,7 @@
[:and [:sequential :int] (f "1") (f "2")] [1 2] => ["1" "2"])))

(deftest multi-humanize-test-428
(is (= {:user {:type ["invalid dispatch value"]}}
(is (= {:user ["invalid dispatch value"]}
(-> (m/explain [:map [:user [:multi {:dispatch :type}]]] {:user nil})
(me/humanize)))))

Expand Down

0 comments on commit 4d739d9

Please sign in to comment.