Skip to content

Commit

Permalink
fix: explain :path of ref schemas
Browse files Browse the repository at this point in the history
The path from a [:ref ::kw] or a [:ref #'Var] to the referred schema
is [0 0] due to the intermediate -pointer. See additions to
get-in-test. Thus the -explainer of a -ref-schema needs to add [0 0]
to the path, instead of the previous [0]. This mirrors the [0 0]
already present in the -walk of -ref-schema.

fixes #1106
  • Loading branch information
opqdonut committed Jan 8, 2025
1 parent 5941195 commit b2db1a6
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/malli/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -1709,7 +1709,7 @@
(let [validator (-memoize (fn [] (-validator (rf))))]
(fn [x] ((validator) x))))
(-explainer [_ path]
(let [explainer (-memoize (fn [] (-explainer (rf) (conj path 0))))]
(let [explainer (-memoize (fn [] (-explainer (rf) (into path [0 0]))))]
(fn [x in acc] ((explainer) x in acc))))
(-parser [_] (->parser -parser))
(-unparser [_] (->parser -unparser))
Expand Down
38 changes: 36 additions & 2 deletions test/malli/core_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,19 @@

(testing "ref schemas"

(let [schema [:ref {:registry {::referred [:map [:foo :int]]}} ::referred]]
(is (nil? (m/explain schema {:foo 2})))
(testing "explain path"
(let [exp (m/explain schema {:foo "2"})]
(is (results= {:value {:foo "2"}
:schema schema
:errors [{:in [:foo]
:path [0 0 :foo]
:schema :int
:value "2"}]}
exp))
(is (form= :int (mu/get-in schema (-> exp :errors first :path)))))))

(testing "invalid refs fail"
(is (thrown?
#?(:clj Exception, :cljs js/Error)
Expand All @@ -640,7 +653,7 @@
(is (results= {:schema ConsCell
:value [1 [2]]
:errors [{:in [1]
:path [0 0 0 1 0 0]
:path [0 0 0 1 0 0 0]
:schema (mu/get-in ConsCell [0 0 0])
:type :malli.core/tuple-size
:value [2]}]}
Expand Down Expand Up @@ -3333,7 +3346,28 @@

(testing "it works"
(is (= User (m/form schema)))
(is (every? (m/validator schema) (mg/sample schema {:seed 100}))))))
(is (every? (m/validator schema) (mg/sample schema {:seed 100}))))

(testing "explain path"
(let [exp (m/explain schema {:id 1})]
(is (results= {:value {:id 1}
:schema User
:errors [{:in [:id]
:path [:id 0]
:schema :string
:value 1}]}
exp))
(is (form= :string (mu/get-in schema (-> exp :errors first :path)))))
(let [explicit-ref [:ref #'UserId]
exp (m/explain explicit-ref 1)]
(is (results= {:value 1
:schema explicit-ref
:errors [{:in []
:path [0 0]
:schema :string
:value 1}]}
exp))
(is (form= :string (mu/get-in explicit-ref (-> exp :errors first :path))))))))

#?(:clj
(deftest roundrobin-var-references
Expand Down
14 changes: 13 additions & 1 deletion test/malli/error_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,8 @@
(m/explain [1 2 :foo])
(me/humanize)))))

(def VarSchema [:map [:foo :int]])

(deftest error-definion-lookup-test
(is (= {:foo ["should be an integer"]}
(-> [:map
Expand Down Expand Up @@ -629,7 +631,17 @@
(= password password2))]]
(m/explain {:password "secret"
:password2 "faarao"})
(me/humanize {:resolve me/-resolve-root-error}))))))
(me/humanize {:resolve me/-resolve-root-error})))))

(testing "refs #1106"
(is (= {:foo ["should be an integer"]}
(me/humanize
(m/explain [:ref #'VarSchema] {:foo "2"})
{:resolve me/-resolve-direct-error})))
(is (= {:foo ["should be an integer"]}
(me/humanize
(m/explain [:ref #'VarSchema] {:foo "2"})
{:resolve me/-resolve-root-error})))))

(deftest limits
(is (= {:a [["should be an int"]]
Expand Down
11 changes: 10 additions & 1 deletion test/malli/util_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@
;; LensSchemas
;;

(def Var :string)

(deftest basic-lens-schema-test
(let [re #"kikka"
int? (m/schema int?)]
Expand Down Expand Up @@ -333,6 +335,8 @@

[:ref {:registry {::a int?, ::b string?}} ::a] 0 ::a
[:ref {:registry {::a int?, ::b string?}} ::a] 1 nil
[:ref #'Var] 0 #'Var
[:ref #'Var] 1 nil

[:schema int?] 0 int?
[:schema int?] 1 nil)
Expand Down Expand Up @@ -439,7 +443,12 @@
(is (form= (mu/get-in (m/schema [:ref {:registry {::a int?, ::b string?}} ::a]) [0]) ::a))
(is (mu/equals (mu/get-in (m/schema [:ref {:registry {::a int?, ::b string?}} ::a]) [0 0]) int?))
(is (form= (mu/get-in (m/schema [:schema {:registry {::a int?, ::b string?}} ::a]) [0]) ::a))
(is (mu/equals (mu/get-in (m/schema [:schema {:registry {::a int?, ::b string?}} ::a]) [0 0]) int?)))
(is (mu/equals (mu/get-in (m/schema [:schema {:registry {::a int?, ::b string?}} ::a]) [0 0]) int?))

(is (form= (mu/get-in (m/schema [:ref #'Var]) [0]) #'Var))
(is (form= (mu/get-in (m/schema [:ref #'Var]) [0 0]) :string))
(is (form= (mu/get-in (m/schema [:schema #'Var]) [0]) #'Var))
(is (form= (mu/get-in (m/schema [:schema #'Var]) [0 0]) :string)))

(deftest dissoc-test
(let [schema [:map {:title "map"}
Expand Down

0 comments on commit b2db1a6

Please sign in to comment.