Skip to content

Commit

Permalink
Ensure and and or are parsed correctly from key specs
Browse files Browse the repository at this point in the history
* fixes #79
  • Loading branch information
ikitommi committed Oct 7, 2017
1 parent 5e0a94d commit 6eb16e8
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 16 deletions.
9 changes: 8 additions & 1 deletion src/spec_tools/impl.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,14 @@
:else x))

(defn polish-un [x]
(-> x polish name keyword))
(some-> x polish name keyword))

(defn parse-keys [form]
(let [m (some->> form (rest) (apply hash-map))]
(cond-> m
(:req m) (update :req #(->> % flatten (keep polish) (into [])))
(:req-un m) (update :req-un #(->> % flatten (keep polish-un) (into [])))
(:opt-un m) (update :opt-un #(->> % (keep polish-un) (into []))))))

(defn extract-keys [form]
(let [{:keys [req opt req-un opt-un]} (some->> form (rest) (apply hash-map))]
Expand Down
2 changes: 1 addition & 1 deletion src/spec_tools/json_schema.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
schema))

(defmethod accept-spec 'clojure.spec.alpha/keys [_ spec children _]
(let [[_ & {:keys [req req-un opt opt-un]}] (impl/extract-form spec)
(let [{:keys [req req-un opt opt-un]} (impl/parse-keys (impl/extract-form spec))
names-un (map name (concat req-un opt-un))
names (map impl/qualified-name (concat req opt))
required (map impl/qualified-name req)
Expand Down
12 changes: 5 additions & 7 deletions src/spec_tools/parse.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,11 @@
(defmethod parse-form :clojure.spec.alpha/unknown [_ _])

(defmethod parse-form 'clojure.spec.alpha/keys [_ form]
(let [{:keys [req opt req-un opt-un]} (some->> form (rest) (apply hash-map))]
{:type :map
:keys (set
(flatten
(concat
(map impl/polish (concat req opt))
(map impl/polish-un (concat req-un opt-un)))))}))
(let [{:keys [req opt req-un opt-un]} (impl/parse-keys form)]
(cond-> {:type :map
:keys (set (concat req opt req-un opt-un))}
(or req req-un) (assoc :keys/req (set (concat req req-un)))
(or opt opt-un) (assoc :keys/opt (set (concat opt opt-un))))))

(defmethod parse-form 'clojure.spec.alpha/or [_ _])

Expand Down
7 changes: 5 additions & 2 deletions test/cljc/spec_tools/core_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,9 @@

(testing "all keys types are extracted"
(is (= {:type :map
:keys #{::age :lat ::truth :uuid}}
:keys #{::age :lat ::truth :uuid}
:keys/req #{::age :lat}
:keys/opt #{::truth :uuid}}

;; named spec
(info/parse-spec
Expand All @@ -432,7 +434,8 @@

(testing "ands and ors are flattened"
(is (= {:type :map
:keys #{::age ::lat ::uuid}}
:keys #{::age ::lat ::uuid}
:keys/req #{::age ::lat ::uuid}}
(info/parse-spec
(s/keys
:req [(or ::age (and ::uuid ::lat))]))))))
Expand Down
33 changes: 28 additions & 5 deletions test/cljc/spec_tools/json_schema_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,16 @@
(s/def ::integer integer?)
(s/def ::string string?)
(s/def ::set #{1 2 3})
(s/def ::keys (s/keys :req-un [::integer]))

(s/def ::a string?)
(s/def ::b string?)
(s/def ::c string?)
(s/def ::d string?)

(s/def ::keys (s/keys :opt [::a]
:opt-un [::a]
:req [::a (or ::b (and ::c ::d))]
:req-un [::a (or ::b (and ::c ::d))]))

(deftest simple-spec-test
(testing "primitive predicates"
Expand All @@ -39,10 +48,24 @@
:properties {"integer" {:type "integer"} "string" {:type "string"}}
:required ["integer"]}))
(is (= (jsc/transform ::keys)
{:type "object",
:properties {"integer" {:type "integer"}},
:required ["integer"],
:title "spec-tools.json-schema-test/keys"}))
{:type "object"
:title "spec-tools.json-schema-test/keys"
:properties {"spec-tools.json-schema-test/a" {:type "string"}
"spec-tools.json-schema-test/b" {:type "string"}
"spec-tools.json-schema-test/c" {:type "string"}
"spec-tools.json-schema-test/d" {:type "string"}
"a" {:type "string"}
"b" {:type "string"}
"c" {:type "string"}
"d" {:type "string"}}
:required ["spec-tools.json-schema-test/a"
"spec-tools.json-schema-test/b"
"spec-tools.json-schema-test/c"
"spec-tools.json-schema-test/d"
"a"
"b"
"c"
"d"]}))
(is (= (jsc/transform (s/or :int integer? :string string?))
{:anyOf [{:type "integer"} {:type "string"}]}))
(is (= (jsc/transform (s/and integer? pos?))
Expand Down
21 changes: 21 additions & 0 deletions test/cljc/spec_tools/parse_test.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(ns spec-tools.parse-test
(:require [clojure.test :refer [deftest is]]
[spec-tools.parse :as parse]
[clojure.spec.alpha :as s]))

(s/def ::a string?)
(s/def ::b string?)
(s/def ::c string?)
(s/def ::d string?)

(s/def ::keys (s/keys :opt [::a]
:opt-un [::a]
:req [::a (or ::b (and ::c ::d))]
:req-un [::a (or ::b (and ::c ::d))]))

(deftest parse-test
(is (= {:type :map
:keys #{:a :b :c :d ::a ::b ::c ::d}
:keys/req #{:a :b :c :d ::a ::b ::c ::d}
:keys/opt #{:a ::a}}
(parse/parse-spec ::keys))))

0 comments on commit 6eb16e8

Please sign in to comment.