-
Notifications
You must be signed in to change notification settings - Fork 2
/
set.clj
100 lines (90 loc) · 3.24 KB
/
set.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
(ns com.timezynk.domain.validation.set
(:require
[clojure.set :as set]
[clojure.test :refer [deftest is testing]]
[com.timezynk.domain.validation.validation-operator :refer [validation-operator]]
[validateur.validation :as v]))
(defn all-of
"All conditions should be true (AND)"
[& rules]
(validation-operator (fn [results] (reduce #(and % %2) results))
(fn [errs] (apply set/union errs))
rules))
(defn- some-of-proto [treshold-func err-wrap-name rules]
(validation-operator (fn [results] (->> results
(filter true?)
count
treshold-func))
(fn [errs] {err-wrap-name (apply set/union errs)})
rules))
(defn some-of
"At least one condition should be true (OR)"
[& rules]
(some-of-proto pos? :or rules))
(defn none-of
"No condition should be true"
[& rules]
(some-of-proto zero? :none rules))
(defn one-of
"One condition should be true (XOR)"
[& rules]
(some-of-proto #(= 1 %) :xor rules))
(defn has [& properties]
(fn [entry]
(let [rule (->> properties
(map #(v/presence-of %))
(apply all-of))]
(rule entry))))
(defn- no-presence-of [attribute]
(fn [entry]
(let [[presence-of?] ((v/presence-of attribute) entry)]
(if presence-of?
[false {attribute #{"have to be blank"}}]
[true {attribute #{}}]))))
(defn has-not [& attributes]
(fn [entry]
(let [rule (->> attributes
(map #(no-presence-of %))
(apply all-of))]
(rule entry))))
(deftest test-sets
(let [func1 (fn [_] [true {}])
func2 (fn [_] [true {}])
func3 (fn [_] [false #{"This is an error"}])
func4 (fn [_] [false #{"This is also an error"}])]
(testing "all-of"
(is (= [true {}]
((all-of func1 func2) "")))
(is (= [false #{"This is an error"}]
((all-of func1 func2 func3) ""))))
(testing "some-of"
(is (= [true {}]
((some-of func1 func3) "")))
(is (= [false {:or #{"This is an error" "This is also an error"}}]
((some-of func3 func4) "")))
(is (= [true {}]
((some-of func4 func3 func2) ""))))
(testing "none-of"
(is (= [true {}]
((none-of func3 func4) "")))
(is (= [false {:none #{"This is also an error"}}]
((none-of func1 func2 func4) ""))))
(testing "one-of"
(is (= [true {}]
((one-of func2 func3 func4) "")))
(is (= [false {:xor #{"This is an error" "This is also an error"}}]
((one-of func1 func2 func3 func4) ""))))))
(deftest test-fields
(testing "has"
(is (= [true {}]
((has :field1 :field2) {:field1 ""
:field2 ""})))
(is (= [false {:field1 #{"can't be blank"}
:field2 #{"can't be blank"}}]
((has :field1 :field2) {:field1 nil}))))
(testing "has-not"
(is (= [true {}]
((has-not :field1 :field2) {})))
(is (= [false {:field1 #{"have to be blank"}}]
((has-not :field1) {:field1 ""
:field2 nil})))))