-
Notifications
You must be signed in to change notification settings - Fork 2
/
validate_type.clj
89 lines (77 loc) · 3.05 KB
/
validate_type.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
(ns com.timezynk.domain.validation.validate-type
(:require
[clojure.test :refer [deftest is]]
[com.timezynk.domain.validation.check :refer [check]]
[spy.core :as spy])
(:import [org.bson.types ObjectId]
[org.joda.time LocalDateTime LocalDate LocalTime]))
(defn- object-id? [x]
(isa? (class x) ObjectId))
(defn- time? [x]
(let [c (class x)]
(or
(isa? c LocalTime)
(isa? c java.time.LocalTime))))
(defn- date-time? [x]
(let [c (class x)]
(or
(isa? c LocalDateTime)
(isa? c java.time.LocalDateTime)
(isa? c java.time.ZonedDateTime))))
(defn- date? [x]
(let [c (class x)]
(or
(isa? c LocalDate)
(isa? c java.time.LocalDate))))
(defn- timestamp? [x]
(and (number? x) (<= 0 x)))
(defn validate-type [attr-name type-name]
(case type-name
:string (check string? attr-name "not a string")
:number (check number? attr-name "not a number")
:integer (check integer? attr-name "not an integer")
:duration (check number? attr-name "not a duration in milliseconds")
:vector (check sequential? attr-name "not sequential")
:map (check map? attr-name "not a map")
:time (check time? attr-name "not a valid time declaration")
:date-time (check date-time? attr-name "not a valid date-time declaration")
:date (check date? attr-name "not a valid date")
:timestamp (check timestamp? attr-name "not a valid timestamp")
:object-id (check object-id? attr-name "not a valid id")
:boolean (check boolean? attr-name "not a boolean")
:any (fn [_] [true #{}])
[false {attr-name {"unknown type" (name type-name)}}]))
(deftest test-object-id
(is (object-id? (ObjectId.)))
(is (not (object-id? (str (ObjectId.))))))
(deftest test-time
(is (time? (LocalTime. "12.03")))
(is (time? (java.time.LocalTime/parse "14:30")))
(is (not (time? "12.03"))))
(deftest test-date-time
(is (date-time? (LocalDateTime. "2020-10-01T12.03")))
(is (date-time? (java.time.LocalDateTime/parse "2020-10-01T12:03")))
(is (date-time? (java.time.ZonedDateTime/parse "2020-10-01T12:03+01:00[CET]")))
(is (not (date-time? (LocalTime. "12.03")))))
(deftest test-date
(is (date? (LocalDate. "2020-10-01")))
(is (date? (java.time.LocalDate/parse "2020-10-01")))
(is (not (date? (LocalDateTime. "2020-10-01")))))
(deftest test-timestamp
(is (timestamp? 12345))
(is (not (timestamp? -12345))))
(deftest test-validate-type
(with-redefs [check (spy/spy check)]
(is (= [true {}]
((validate-type :field :string) "")))
(is (= [false {:field "not a string"}]
((validate-type :field :string) 1)))
(is (= [true {}]
((validate-type :field :object-id) (ObjectId.))))
(is (= [false {:field "not a valid id"}]
((validate-type :field :object-id) (str (ObjectId.)))))
(is (= [true #{}]
((validate-type :field :any) "")))
(is (= [false {:field {"unknown type" "not-a-type"}}]
(validate-type :field :not-a-type)))
(is (spy/called-n-times? check 4))))