From c0ac6faf105c5e5e5dca9fd322d2b8209885ae95 Mon Sep 17 00:00:00 2001 From: Joel Kaasinen Date: Wed, 8 Jan 2025 09:18:05 +0200 Subject: [PATCH 1/2] fix: explain :path of ref schemas 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 --- src/malli/core.cljc | 2 +- test/malli/core_test.cljc | 38 ++++++++++++++++++++++++++++++++++++-- test/malli/error_test.cljc | 14 +++++++++++++- test/malli/util_test.cljc | 11 ++++++++++- 4 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/malli/core.cljc b/src/malli/core.cljc index b5d7720c7..fead6e24b 100644 --- a/src/malli/core.cljc +++ b/src/malli/core.cljc @@ -1732,7 +1732,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)) diff --git a/test/malli/core_test.cljc b/test/malli/core_test.cljc index 28a627db3..617943971 100644 --- a/test/malli/core_test.cljc +++ b/test/malli/core_test.cljc @@ -625,6 +625,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) @@ -641,7 +654,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]}]} @@ -3359,7 +3372,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 diff --git a/test/malli/error_test.cljc b/test/malli/error_test.cljc index ad9923fcb..6f6906250 100644 --- a/test/malli/error_test.cljc +++ b/test/malli/error_test.cljc @@ -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 @@ -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"]] diff --git a/test/malli/util_test.cljc b/test/malli/util_test.cljc index 5e745ff8c..8bf3e687c 100644 --- a/test/malli/util_test.cljc +++ b/test/malli/util_test.cljc @@ -276,6 +276,8 @@ ;; LensSchemas ;; +(def Var :string) + (deftest basic-lens-schema-test (let [re #"kikka" int? (m/schema int?)] @@ -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) @@ -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"} From 52367ff0daf84a0066c4cdc5065ba33e71b336aa Mon Sep 17 00:00:00 2001 From: Joel Kaasinen Date: Wed, 8 Jan 2025 11:18:01 +0200 Subject: [PATCH 2/2] doc: update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d927ea96..0946f2740 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Malli is in well matured [alpha](README.md#alpha). * Docs: elaborate optional-keys and required-keys [#1117](https://github.com/metosin/malli/pull/1117) * **BREAKING** Output of `parse` now uses new `malli.core.Tag` and `malli.core.Tags` records for `:orn`, `:multi`, `:altn`, `:catn` etc. [#1123](https://github.com/metosin/malli/issues/1123) [#1153](https://github.com/metosin/malli/issues/1153) * See [Parsing](#parsing-values) and [Unparsing](#unparsing-values) for docs. +* FIX: `:path` when explaining `:ref` errors [#1106](https://github.com/metosin/malli/issues/1106) ## 0.17.0 (2024-12-08)