|
14 | 14 | error->string |
15 | 15 | errors->data |
16 | 16 | named-error? |
17 | | - validation-error?]] |
| 17 | + validation-error? |
| 18 | + leaves-and-paths |
| 19 | + errors->paths]] |
18 | 20 | [xapi-schema.schemata.json :as json] |
19 | 21 | [schema.core :as s |
20 | 22 | :include-macros true] |
|
29 | 31 | [clojure.walk :refer [postwalk]] |
30 | 32 | [xapi-schema.support.data :as d])) |
31 | 33 |
|
| 34 | +(describe |
| 35 | + "leaves-and-paths" |
| 36 | + (it "returns a map of leaves to paths" |
| 37 | + (should= {"h" ["a" "e" "f" "g"] |
| 38 | + "m" ["a" "e" "f" "l"] |
| 39 | + "d" ["a" "b" "c"] |
| 40 | + "j" ["i"]} |
| 41 | + (leaves-and-paths {"a"{"e" {"f" {"g" "h" |
| 42 | + "l" "m"}} |
| 43 | + "b" {"c" "d"}} |
| 44 | + "i" "j"}))) |
| 45 | + (it "consumes all nested data" |
| 46 | + (should= {"h" [0 "a" "e" "f" "g"] |
| 47 | + "m" [0 "a" "e" "f" "l"] |
| 48 | + "d" [0 "a" "b" "c"] |
| 49 | + "j" [0 "i"] |
| 50 | + "n" [0 "a" "b" "k" 0] |
| 51 | + "o" [0 "a" "b" "k" 1] |
| 52 | + "q" [0 "a" "b" "k" 2 "p"]} |
| 53 | + (leaves-and-paths [{"a"{"e" {"f" {"g" "h" |
| 54 | + "l" "m"}} |
| 55 | + "b" {"c" "d" |
| 56 | + "k" ["n" "o" {"p" "q"}]}} |
| 57 | + "i" "j"}])))) |
| 58 | + |
32 | 59 | (describe "check-type" |
33 | 60 | (with pred (check-type "Activity")) |
34 | 61 | (it "returns a predicate that checks for the given objectType" |
|
75 | 102 | "given a missing key error" |
76 | 103 | (with err (s/check {(s/required-key "foo") s/Str} {})) |
77 | 104 | (it "converts it to an English string" |
78 | | - (should= "Missing" |
| 105 | + (should= "Missing required key" |
79 | 106 | (error->string (get |
80 | 107 | @err |
81 | 108 | "foo"))))) |
82 | 109 | (context |
83 | 110 | "given a disallowed key error" |
84 | 111 | (with err (s/check {} {"foo" "bar"})) |
85 | 112 | (it "converts it to an English string" |
86 | | - (should= "Not Allowed" |
| 113 | + (should= "Key not allowed" |
87 | 114 | (error->string (get |
88 | 115 | @err |
89 | 116 | "foo"))))) |
90 | 117 | (context |
91 | 118 | "given a NOT validation error" |
92 | 119 | (context |
93 | 120 | "from a predicate" |
94 | | - (with err (su/validation-error-explain ;; expect it to be coerced! |
95 | | - (s/check (s/pred (fn [bar] |
96 | | - (= "bar" bar)) "a bar") "foo"))) |
| 121 | + (with err |
| 122 | + (s/check (s/pred (fn [bar] |
| 123 | + (= "bar" bar)) "a bar") "foo")) |
97 | 124 | (it "converts it to an English string" |
98 | 125 | (should= "Not a bar: foo" |
99 | 126 | (error->string @err)))) |
100 | 127 | (context |
101 | 128 | "from a predicate that throws" |
102 | | - (with err (su/validation-error-explain |
103 | | - (s/check (s/pred seq "a sequable thing") true))) |
| 129 | + (with err |
| 130 | + (s/check (s/pred seq "a sequable thing") true)) |
104 | 131 | (it "mentions it" |
105 | 132 | (should= "Not a sequable thing: true (threw)" |
106 | 133 | (error->string @err)))) |
107 | 134 | (context |
108 | 135 | "from a seq schema" |
109 | | - (with err (su/validation-error-explain |
110 | | - (s/check [] {}))) |
| 136 | + (with err |
| 137 | + (s/check [] {})) |
111 | 138 | (it "converts" |
112 | 139 | (should= "Not sequential: {}" |
113 | 140 | (error->string @err)))) |
114 | 141 | (context |
115 | 142 | "from a map schema" |
116 | | - (with err (su/validation-error-explain |
117 | | - (s/check {} []))) |
| 143 | + (with err |
| 144 | + (s/check {} [])) |
118 | 145 | (it "converts" |
119 | 146 | (should= "Not map: []" |
120 | 147 | (error->string @err)))) |
121 | 148 | (context |
122 | 149 | "from an integer" |
123 | | - (with err (su/validation-error-explain |
124 | | - (s/check s/Int "foo"))) |
| 150 | + (with err |
| 151 | + (s/check s/Int "foo")) |
125 | 152 | (it "converts" |
126 | | - (should= "Not an integer: foo" |
| 153 | + (should= "Not integer: foo" |
127 | 154 | (error->string @err)))) |
128 | 155 | (context |
129 | 156 | "from s/Str" |
130 | | - (with err (su/validation-error-explain |
131 | | - (s/check s/Str 1))) |
| 157 | + (with err |
| 158 | + (s/check s/Str 1)) |
132 | 159 | (it "converts" |
133 | | - (should= "Not a string: 1" |
| 160 | + (should= "Not string: 1" |
134 | 161 | (error->string @err)))) |
135 | 162 | (context |
136 | 163 | "from s/Num" |
137 | | - (with err (su/validation-error-explain |
138 | | - (s/check s/Num "foo"))) |
| 164 | + (with err |
| 165 | + (s/check s/Num "foo")) |
139 | 166 | (it "converts" |
140 | | - (should= "Not a number: foo" |
| 167 | + (should= "Not number: foo" |
141 | 168 | (error->string @err)))) |
142 | 169 | (context |
143 | 170 | "from s/Bool" |
144 | | - (with err (su/validation-error-explain |
145 | | - (s/check s/Bool "foo"))) |
| 171 | + (with err |
| 172 | + (s/check s/Bool "foo")) |
146 | 173 | (it "converts" |
147 | | - (should= "Not a boolean: foo" |
| 174 | + (should= "Not boolean: foo" |
148 | 175 | (error->string @err)))))) |
149 | 176 |
|
150 | | - (describe |
151 | | - "named-error?" |
152 | | - (it "returns true if the error is a named error" |
153 | | - (should (named-error? (s/check (s/named s/Str "foo") 1))))) |
| 177 | + (context |
| 178 | + "error processing" |
154 | 179 |
|
155 | | - (describe |
156 | | - "validation-error?" |
157 | | - (it "returns true if the error is a validation error" |
158 | | - (should (validation-error? (s/check s/Str 1))))) |
| 180 | + (with schema (s/named |
| 181 | + {(s/required-key "foo") s/Str |
| 182 | + (s/required-key "bar") s/Num |
| 183 | + (s/required-key "baz") s/Int |
| 184 | + (s/required-key "quxx") s/Bool |
| 185 | + (s/required-key "map") {} |
| 186 | + (s/required-key "string-seq") [s/Str] |
| 187 | + (s/required-key "not-there") s/Any |
| 188 | + (s/required-key "equals") (s/eq "foo") |
| 189 | + (s/required-key "enum") (s/enum "foo" "bar" "baz") |
| 190 | + (s/required-key "one") [(s/one s/Str "at least one string")]} |
| 191 | + "bob")) |
159 | 192 |
|
160 | | - (describe |
161 | | - "errors->data" |
162 | | - (context |
163 | | - "with nested named and validation errors" |
164 | | - (with schema (s/named |
165 | | - {(s/required-key "foo") s/Str |
166 | | - (s/required-key "bar") s/Num |
167 | | - (s/required-key "baz") s/Int |
168 | | - (s/required-key "quxx") s/Bool |
169 | | - (s/required-key "map") {} |
170 | | - (s/required-key "string-seq") [s/Str] |
171 | | - (s/required-key "not-there") s/Any |
172 | | - (s/required-key "equals") (s/eq "foo") |
173 | | - (s/required-key "enum") (s/enum "foo" "bar" "baz") |
174 | | - (s/required-key "one") [(s/one s/Str "at least one string")]} |
175 | | - "bob")) |
176 | | - (with err (s/check @schema {"foo" 1 |
177 | | - "bar" true |
178 | | - "baz" 1.1 |
179 | | - "quxx" "foo" |
180 | | - "map" [] |
181 | | - "string-seq" {} |
182 | | - "unknown-key" "hey" |
183 | | - "equals" "bar" |
184 | | - "enum" "quxx" |
185 | | - "one" [] |
186 | | - })) |
187 | | - (it "converts all error objects to data" |
188 | | - (should-not-throw |
189 | | - (postwalk |
190 | | - (fn [node] |
191 | | - (if (or (named-error? node) |
192 | | - (validation-error? node)) |
193 | | - (throw (#+clj Exception. |
194 | | - #+cljs js/Error. "error obj found!")) |
195 | | - node)) |
196 | | - (errors->data @err)))) |
197 | | - (it "converts all predicate and scalar errors to strings" |
198 | | - (should= {"unknown-key" "Not Allowed" |
199 | | - "not-there" "Missing" |
200 | | - "string-seq" "Not sequential: {}" |
201 | | - "map" "Not map: []" |
202 | | - "quxx" "Not a boolean: foo" |
203 | | - "baz" "Not an integer: 1.1" |
204 | | - "bar" "Not a number: true" |
205 | | - "foo" "Not a string: 1" |
206 | | - "equals" "Not foo: bar" |
207 | | - "enum" "Not in #{\"foo\" \"bar\" \"baz\"}: quxx" |
208 | | - "one" ["Not present: at least one string"]} |
209 | | - (errors->data @err)))) |
210 | | - (context "given some xapi validation cases" |
211 | | - (it "parses an agent objectType error" |
212 | | - (should-not-throw |
213 | | - (errors->data |
214 | | - (s/check json/Statement |
215 | | - (assoc d/long-statement |
216 | | - "actor" |
217 | | - {"mbox" "mailto:milt@yetanalytics.com" |
218 | | - "objectType" "NotAnAgent"})))))))) |
| 193 | + (with err (s/check @schema {"foo" 1 |
| 194 | + "bar" true |
| 195 | + "baz" 1.1 |
| 196 | + "quxx" "foo" |
| 197 | + "map" [] |
| 198 | + "string-seq" {} |
| 199 | + "unknown-key" "hey" |
| 200 | + "equals" "bar" |
| 201 | + "enum" "quxx" |
| 202 | + "one" [] |
| 203 | + })) |
| 204 | + |
| 205 | + (describe |
| 206 | + "named-error?" |
| 207 | + (it "returns true if the error is a named error" |
| 208 | + (should (named-error? (s/check (s/named s/Str "foo") 1))))) |
| 209 | + |
| 210 | + (describe |
| 211 | + "validation-error?" |
| 212 | + (it "returns true if the error is a validation error" |
| 213 | + (should (validation-error? (s/check s/Str 1))))) |
| 214 | + |
| 215 | + (describe |
| 216 | + "errors->data" |
| 217 | + (context |
| 218 | + "with nested named and validation errors" |
| 219 | + (it "converts all error objects to data" |
| 220 | + (should-not-throw |
| 221 | + (postwalk |
| 222 | + (fn [node] |
| 223 | + (if (or (named-error? node) |
| 224 | + (validation-error? node)) |
| 225 | + (throw (#+clj Exception. |
| 226 | + #+cljs js/Error. "error obj found!")) |
| 227 | + node)) |
| 228 | + (errors->data @err)))) |
| 229 | + (it "converts all predicate and scalar errors to strings" |
| 230 | + (should= {"unknown-key" "Key not allowed" |
| 231 | + "not-there" "Missing required key" |
| 232 | + "string-seq" "Not sequential: {}" |
| 233 | + "map" "Not map: []" |
| 234 | + "quxx" "Not boolean: foo" |
| 235 | + "baz" "Not integer: 1.1" |
| 236 | + "bar" "Not number: true" |
| 237 | + "foo" "Not string: 1" |
| 238 | + "equals" "Not foo: bar" |
| 239 | + "enum" "Not in #{\"foo\" \"bar\" \"baz\"}: quxx" |
| 240 | + "one" ["Not present: at least one string"]} |
| 241 | + (errors->data @err)))) |
| 242 | + (context "given some xapi validation cases" |
| 243 | + (it "parses an agent objectType error" |
| 244 | + (should-not-throw |
| 245 | + (errors->data |
| 246 | + (s/check json/Statement |
| 247 | + (assoc d/long-statement |
| 248 | + "actor" |
| 249 | + {"mbox" "mailto:milt@yetanalytics.com" |
| 250 | + "objectType" "NotAnAgent"}))))))) |
| 251 | + (describe |
| 252 | + "errors->paths" |
| 253 | + (it "returns a map" |
| 254 | + (should (map? (errors->paths @err)))) |
| 255 | + (it "maps errors to their paths" |
| 256 | + (should= (errors->paths @err) |
| 257 | + {"Key not allowed" ["unknown-key"] |
| 258 | + "Missing required key" ["not-there"] |
| 259 | + "Not sequential: {}" ["string-seq"] |
| 260 | + "Not map: []" ["map"] |
| 261 | + "Not boolean: foo" ["quxx"] |
| 262 | + "Not integer: 1.1" ["baz"] |
| 263 | + "Not number: true" ["bar"] |
| 264 | + "Not string: 1" ["foo"] |
| 265 | + "Not foo: bar" ["equals"] |
| 266 | + "Not in #{\"foo\" \"bar\" \"baz\"}: quxx" ["enum"] |
| 267 | + "Not present: at least one string" ["one" 0]}))))) |
0 commit comments