apes 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rubocop.yml +82 -0
- data/.travis-gemfile +15 -0
- data/.travis.yml +15 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +22 -0
- data/README.md +177 -0
- data/Rakefile +44 -0
- data/apes.gemspec +34 -0
- data/doc/Apes.html +130 -0
- data/doc/Apes/Concerns.html +127 -0
- data/doc/Apes/Concerns/Errors.html +1089 -0
- data/doc/Apes/Concerns/Pagination.html +636 -0
- data/doc/Apes/Concerns/Request.html +766 -0
- data/doc/Apes/Concerns/Response.html +940 -0
- data/doc/Apes/Controller.html +1100 -0
- data/doc/Apes/Errors.html +125 -0
- data/doc/Apes/Errors/AuthenticationError.html +133 -0
- data/doc/Apes/Errors/BadRequestError.html +157 -0
- data/doc/Apes/Errors/BaseError.html +320 -0
- data/doc/Apes/Errors/InvalidDataError.html +157 -0
- data/doc/Apes/Errors/MissingDataError.html +157 -0
- data/doc/Apes/Model.html +378 -0
- data/doc/Apes/PaginationCursor.html +2138 -0
- data/doc/Apes/RuntimeConfiguration.html +909 -0
- data/doc/Apes/Serializers.html +125 -0
- data/doc/Apes/Serializers/JSON.html +389 -0
- data/doc/Apes/Serializers/JWT.html +452 -0
- data/doc/Apes/Serializers/List.html +347 -0
- data/doc/Apes/UrlsParser.html +1432 -0
- data/doc/Apes/Validators.html +125 -0
- data/doc/Apes/Validators/BaseValidator.html +278 -0
- data/doc/Apes/Validators/BooleanValidator.html +494 -0
- data/doc/Apes/Validators/EmailValidator.html +350 -0
- data/doc/Apes/Validators/PhoneValidator.html +375 -0
- data/doc/Apes/Validators/ReferenceValidator.html +372 -0
- data/doc/Apes/Validators/TimestampValidator.html +640 -0
- data/doc/Apes/Validators/UuidValidator.html +372 -0
- data/doc/Apes/Validators/ZipCodeValidator.html +372 -0
- data/doc/Apes/Version.html +189 -0
- data/doc/ApplicationController.html +547 -0
- data/doc/Concerns.html +128 -0
- data/doc/Concerns/ErrorHandling.html +826 -0
- data/doc/Concerns/PaginationHandling.html +463 -0
- data/doc/Concerns/RequestHandling.html +512 -0
- data/doc/Concerns/ResponseHandling.html +579 -0
- data/doc/Errors.html +126 -0
- data/doc/Errors/AuthenticationError.html +123 -0
- data/doc/Errors/BadRequestError.html +147 -0
- data/doc/Errors/BaseError.html +289 -0
- data/doc/Errors/InvalidDataError.html +147 -0
- data/doc/Errors/MissingDataError.html +147 -0
- data/doc/Model.html +315 -0
- data/doc/PaginationCursor.html +764 -0
- data/doc/Serializers.html +126 -0
- data/doc/Serializers/JSON.html +253 -0
- data/doc/Serializers/JWT.html +253 -0
- data/doc/Serializers/List.html +245 -0
- data/doc/Validators.html +126 -0
- data/doc/Validators/BaseValidator.html +209 -0
- data/doc/Validators/BooleanValidator.html +391 -0
- data/doc/Validators/EmailValidator.html +298 -0
- data/doc/Validators/PhoneValidator.html +313 -0
- data/doc/Validators/ReferenceValidator.html +284 -0
- data/doc/Validators/TimestampValidator.html +476 -0
- data/doc/Validators/UuidValidator.html +310 -0
- data/doc/Validators/ZipCodeValidator.html +310 -0
- data/doc/_index.html +435 -0
- data/doc/class_list.html +58 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +339 -0
- data/doc/file.README.html +252 -0
- data/doc/file_list.html +60 -0
- data/doc/frames.html +26 -0
- data/doc/index.html +252 -0
- data/doc/js/app.js +219 -0
- data/doc/js/full_list.js +181 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +615 -0
- data/doc/top-level-namespace.html +112 -0
- data/lib/apes.rb +40 -0
- data/lib/apes/concerns/errors.rb +111 -0
- data/lib/apes/concerns/pagination.rb +81 -0
- data/lib/apes/concerns/request.rb +237 -0
- data/lib/apes/concerns/response.rb +74 -0
- data/lib/apes/controller.rb +77 -0
- data/lib/apes/errors.rb +38 -0
- data/lib/apes/model.rb +94 -0
- data/lib/apes/pagination_cursor.rb +152 -0
- data/lib/apes/runtime_configuration.rb +80 -0
- data/lib/apes/serializers.rb +88 -0
- data/lib/apes/urls_parser.rb +233 -0
- data/lib/apes/validators.rb +234 -0
- data/lib/apes/version.rb +24 -0
- data/spec/apes/concerns/errors_spec.rb +141 -0
- data/spec/apes/concerns/pagination_spec.rb +114 -0
- data/spec/apes/concerns/request_spec.rb +244 -0
- data/spec/apes/concerns/response_spec.rb +79 -0
- data/spec/apes/controller_spec.rb +54 -0
- data/spec/apes/errors_spec.rb +14 -0
- data/spec/apes/models_spec.rb +148 -0
- data/spec/apes/pagination_cursor_spec.rb +113 -0
- data/spec/apes/runtime_configuration_spec.rb +100 -0
- data/spec/apes/serializers_spec.rb +70 -0
- data/spec/apes/urls_parser_spec.rb +150 -0
- data/spec/apes/validators_spec.rb +237 -0
- data/spec/spec_helper.rb +30 -0
- data/views/_included.json.jbuilder +9 -0
- data/views/_pagination.json.jbuilder +9 -0
- data/views/collection.json.jbuilder +4 -0
- data/views/errors/400.json.jbuilder +9 -0
- data/views/errors/403.json.jbuilder +7 -0
- data/views/errors/404.json.jbuilder +6 -0
- data/views/errors/422.json.jbuilder +19 -0
- data/views/errors/500.json.jbuilder +12 -0
- data/views/errors/501.json.jbuilder +7 -0
- data/views/layouts/general.json.jbuilder +36 -0
- data/views/object.json.jbuilder +4 -0
- metadata +262 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of the apes gem. Copyright (C) 2016 and above Shogun <shogun@cowtech.it>.
|
3
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
4
|
+
#
|
5
|
+
|
6
|
+
require "spec_helper"
|
7
|
+
|
8
|
+
describe Apes::Serializers::List do
|
9
|
+
describe ".load" do
|
10
|
+
it "split a string" do
|
11
|
+
expect(Apes::Serializers::List.load(", 1,2 4,,3,A , B ")).to eq(["1", "2 4", "3", "A", "B"])
|
12
|
+
end
|
13
|
+
|
14
|
+
it "always returns a array" do
|
15
|
+
expect(Apes::Serializers::List.load(nil)).to eq([])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe ".dump" do
|
20
|
+
it "encodes everything as an array" do
|
21
|
+
expect(Apes::Serializers::List.dump([])).to eq("")
|
22
|
+
expect(Apes::Serializers::List.dump([1, "2", 3])).to eq("1,2,3")
|
23
|
+
expect(Apes::Serializers::List.dump(1)).to eq("1")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Apes::Serializers::JSON do
|
29
|
+
describe ".load" do
|
30
|
+
it "load a JSON object" do
|
31
|
+
expect(Apes::Serializers::JSON.load("{\"1\": 2}")).to eq({"1" => 2})
|
32
|
+
end
|
33
|
+
|
34
|
+
it "an Hash is returned with indifferent access" do
|
35
|
+
expect(Apes::Serializers::JSON.load("{\"1\": 2}")).to be_a(HashWithIndifferentAccess)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "fallbacks to default for invalid JSON" do
|
39
|
+
expect(Apes::Serializers::JSON.load("\"", false, "A")).to eq("A")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe ".dump" do
|
44
|
+
it "encodes input as JSON" do
|
45
|
+
expect(Apes::Serializers::JSON.dump({a: "B"})).to eq("{\"a\":\"B\"}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe Apes::Serializers::JWT do
|
51
|
+
describe ".load" do
|
52
|
+
it "load a JSON object" do
|
53
|
+
expect(Apes::Serializers::JWT.load("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJkYXRhIiwic3ViIjp7IjEiOjJ9fQ.jqhJuB0xtO7Xyk_T8X_rwOKE96Q7GBxWR5NBxfW5xWE")).to eq({"1" => 2})
|
54
|
+
end
|
55
|
+
|
56
|
+
it "an Hash is returned with indifferent access" do
|
57
|
+
expect(Apes::Serializers::JWT.load("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJkYXRhIiwic3ViIjp7IjEiOjJ9fQ.jqhJuB0xtO7Xyk_T8X_rwOKE96Q7GBxWR5NBxfW5xWE")).to be_a(HashWithIndifferentAccess)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "fallbacks to default for invalid JSON" do
|
61
|
+
expect(Apes::Serializers::JWT.load("\"", false, "A")).to eq("A")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe ".dump" do
|
66
|
+
it "encodes input as JSON" do
|
67
|
+
expect(Apes::Serializers::JWT.dump({a: "B"})).to eq("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJkYXRhIiwic3ViIjp7ImEiOiJCIn19.mWyWy9SDzOlBLJW1b4ICw4QZwoGDU836ED5EALZnjeU")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of the apes gem. Copyright (C) 2016 and above Shogun <shogun@cowtech.it>.
|
3
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
4
|
+
#
|
5
|
+
|
6
|
+
require "spec_helper"
|
7
|
+
|
8
|
+
describe Apes::UrlsParser do
|
9
|
+
describe ".instance" do
|
10
|
+
it "should return a singleton" do
|
11
|
+
first = Apes::UrlsParser.instance
|
12
|
+
expect(Apes::UrlsParser.instance).to be(first)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should force recreation of a new singleton" do
|
16
|
+
original = Apes::UrlsParser.instance
|
17
|
+
expect(Apes::UrlsParser.instance).to be(original)
|
18
|
+
expect(Apes::UrlsParser.instance(true)).not_to be(original)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#url?" do
|
23
|
+
it "should recognize whether a text is a url" do
|
24
|
+
expect(Apes::UrlsParser.instance.url?("http://google.it")).to be_truthy
|
25
|
+
expect(Apes::UrlsParser.instance.url?("google.co")).to be_truthy
|
26
|
+
expect(Apes::UrlsParser.instance.url?("fab.foog.google.co")).to be_truthy
|
27
|
+
expect(Apes::UrlsParser.instance.url?("google.co:123/abc?query=a&utc=b#whatever")).to be_truthy
|
28
|
+
expect(Apes::UrlsParser.instance.url?("google.ca#123")).to be_truthy
|
29
|
+
expect(Apes::UrlsParser.instance.url?("google.c")).to be_falsey
|
30
|
+
expect(Apes::UrlsParser.instance.url?("http://google.cowtech")).to be_falsey
|
31
|
+
expect(Apes::UrlsParser.instance.url?("http://google.it::123")).to be_falsey
|
32
|
+
expect(Apes::UrlsParser.instance.url?("fab..foog.google.co")).to be_falsey
|
33
|
+
expect(Apes::UrlsParser.instance.url?("test@google.com")).to be_falsey
|
34
|
+
expect(Apes::UrlsParser.instance.url?("http://127.0.0.1")).to be_truthy
|
35
|
+
expect(Apes::UrlsParser.instance.url?("127.0.0.1")).to be_truthy
|
36
|
+
expect(Apes::UrlsParser.instance.url?("http://[1762:0:0:0:0:B03:1:AF18]")).to be_truthy
|
37
|
+
expect(Apes::UrlsParser.instance.url?("[1762::B03:1:AF18]")).to be_truthy
|
38
|
+
expect(Apes::UrlsParser.instance.url?("[::127.0.0.1]")).to be_truthy
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#email?" do
|
43
|
+
it "should recognize whether a text is a email" do
|
44
|
+
expect(Apes::UrlsParser.instance.email?("abc@google.it")).to be_truthy
|
45
|
+
expect(Apes::UrlsParser.instance.email?("abc.cde@google.co")).to be_truthy
|
46
|
+
expect(Apes::UrlsParser.instance.email?("ab'c.cde@google.co")).to be_truthy
|
47
|
+
expect(Apes::UrlsParser.instance.email?("abc-af_123@fab.foog.google.co")).to be_truthy
|
48
|
+
expect(Apes::UrlsParser.instance.email?("ad$1@local.com")).to be_falsey
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#domain?" do
|
53
|
+
it "should recognize whether a text is a domain" do
|
54
|
+
expect(Apes::UrlsParser.instance.domain?("google.it")).to be_truthy
|
55
|
+
expect(Apes::UrlsParser.instance.domain?("google.co")).to be_truthy
|
56
|
+
expect(Apes::UrlsParser.instance.domain?("fab.foog.google.co")).to be_truthy
|
57
|
+
expect(Apes::UrlsParser.instance.domain?("google.co:123/abc?query=a&utc=b#whatever")).to be_falsey
|
58
|
+
expect(Apes::UrlsParser.instance.domain?("google.c")).to be_falsey
|
59
|
+
expect(Apes::UrlsParser.instance.domain?("google.it:123")).to be_falsey
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#shortened?" do
|
64
|
+
it "should recognize whether a URL is a shortened one" do
|
65
|
+
expect(Apes::UrlsParser.instance.shortened?("https://bit.ly/ABC")).to be_truthy
|
66
|
+
expect(Apes::UrlsParser.instance.shortened?("bit.ly/ABC")).to be_truthy
|
67
|
+
expect(Apes::UrlsParser.instance.shortened?("bit.ly/ACC")).to be_truthy
|
68
|
+
expect(Apes::UrlsParser.instance.shortened?("cow.tc/ACC")).to be_falsey
|
69
|
+
expect(Apes::UrlsParser.instance.shortened?("cow.tc/ACC", "cow.tc")).to be_truthy
|
70
|
+
expect(Apes::UrlsParser.instance.shortened?("abit.ly/ACC")).to be_falsey
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#extract_urls" do
|
75
|
+
it "should extract URLS from a text" do
|
76
|
+
text = "
|
77
|
+
This is a pretty complex text. It has a URL without a domain which is google.it, also it contains a separator and now let's also put two
|
78
|
+
overlapping URLs http://cowtech.it and http://cowtech.it/en and, finally, a shortened one http://bit.ly/1000 and one using custom domain
|
79
|
+
http://cnn.it/1GFkZQs and email test@gmail.com. Fun, isn't it?
|
80
|
+
"
|
81
|
+
|
82
|
+
expect(Apes::UrlsParser.instance.extract_urls(text)).to eq(["google.it", "http://cowtech.it", "http://cowtech.it/en", "http://bit.ly/1000", "http://cnn.it/1GFkZQs"])
|
83
|
+
expect(Apes::UrlsParser.instance.extract_urls(text, sort: :asc)).to eq(["google.it", "http://cowtech.it", "http://bit.ly/1000", "http://cowtech.it/en", "http://cnn.it/1GFkZQs"])
|
84
|
+
expect(Apes::UrlsParser.instance.extract_urls(text, sort: :desc)).to eq(["http://cnn.it/1GFkZQs", "http://cowtech.it/en", "http://bit.ly/1000", "http://cowtech.it", "google.it"])
|
85
|
+
expect(Apes::UrlsParser.instance.extract_urls(text, mode: :shortened)).to eq(["http://bit.ly/1000"])
|
86
|
+
expect(Apes::UrlsParser.instance.extract_urls(text, mode: :unshortened)).to eq(["google.it", "http://cowtech.it", "http://cowtech.it/en", "http://cnn.it/1GFkZQs"])
|
87
|
+
expect(Apes::UrlsParser.instance.extract_urls(text, mode: :shortened, shortened_domains: ["cnn.it"])).to eq(["http://bit.ly/1000", "http://cnn.it/1GFkZQs"])
|
88
|
+
expect(Apes::UrlsParser.instance.extract_urls(text, mode: :unshortened, shortened_domains: ["cnn.it"])).to eq(["google.it", "http://cowtech.it", "http://cowtech.it/en"])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#replace_urls" do
|
93
|
+
it "should replace URLS in a text" do
|
94
|
+
text = "
|
95
|
+
This is a pretty complex text. It has a URL without a domain which is google.it, also it contains a separator and now let's also put two
|
96
|
+
overlapping URLs http://cowtech.it and http://cowtech.it/en and, finally, a shortened one http://bit.ly/1000 and one using custom domain
|
97
|
+
http://cnn.it/1GFkZQs. Fun, isn't it?
|
98
|
+
"
|
99
|
+
|
100
|
+
replacements = {
|
101
|
+
"http://cowtech.it" => "A",
|
102
|
+
"http://cowtech.it/en" => "B",
|
103
|
+
"http://bit.ly/1000" => "C",
|
104
|
+
"http://cnn.it/1GFkZQs" => "D"
|
105
|
+
}
|
106
|
+
|
107
|
+
expect(Apes::UrlsParser.instance.replace_urls(text, replacements: replacements)).to eq("
|
108
|
+
This is a pretty complex text. It has a URL without a domain which is google.it, also it contains a separator and now let's also put two
|
109
|
+
overlapping URLs http://A and http://B and, finally, a shortened one http://C and one using custom domain
|
110
|
+
http://D. Fun, isn't it?
|
111
|
+
")
|
112
|
+
|
113
|
+
expect(Apes::UrlsParser.instance.replace_urls(text, replacements: replacements, mode: :unshortened)).to eq("
|
114
|
+
This is a pretty complex text. It has a URL without a domain which is google.it, also it contains a separator and now let's also put two
|
115
|
+
overlapping URLs http://A and http://B and, finally, a shortened one http://bit.ly/1000 and one using custom domain
|
116
|
+
http://D. Fun, isn't it?
|
117
|
+
")
|
118
|
+
|
119
|
+
expect(Apes::UrlsParser.instance.replace_urls(text, replacements: replacements, mode: :shortened)).to eq("
|
120
|
+
This is a pretty complex text. It has a URL without a domain which is google.it, also it contains a separator and now let's also put two
|
121
|
+
overlapping URLs http://cowtech.it and http://cowtech.it/en and, finally, a shortened one http://C and one using custom domain
|
122
|
+
http://cnn.it/1GFkZQs. Fun, isn't it?
|
123
|
+
")
|
124
|
+
|
125
|
+
expect(Apes::UrlsParser.instance.replace_urls(text, replacements: replacements, mode: :shortened, shortened_domains: ["cnn.it"])).to eq("
|
126
|
+
This is a pretty complex text. It has a URL without a domain which is google.it, also it contains a separator and now let's also put two
|
127
|
+
overlapping URLs http://cowtech.it and http://cowtech.it/en and, finally, a shortened one http://C and one using custom domain
|
128
|
+
http://D. Fun, isn't it?
|
129
|
+
")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "#clean" do
|
134
|
+
it "should remove separators after a url" do
|
135
|
+
expect(Apes::UrlsParser.instance.clean(" http://google.it ")).to eq("http://google.it")
|
136
|
+
expect(Apes::UrlsParser.instance.clean(" http://google.it,")).to eq("http://google.it")
|
137
|
+
expect(Apes::UrlsParser.instance.clean(" http://google.it.")).to eq("http://google.it")
|
138
|
+
expect(Apes::UrlsParser.instance.clean(" http://google.it:")).to eq("http://google.it")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "#hashify" do
|
143
|
+
it "should generate a hash out of a URL" do
|
144
|
+
expect(Apes::UrlsParser.instance.hashify("google.it")).to eq("dae16e97dcaa41bdace5765826a28a4192b7f2ec9d96993d158ef0413fd3cab5")
|
145
|
+
expect(Apes::UrlsParser.instance.hashify("http://google.it")).to eq("dae16e97dcaa41bdace5765826a28a4192b7f2ec9d96993d158ef0413fd3cab5")
|
146
|
+
expect(Apes::UrlsParser.instance.hashify("bit.ly/1000")).to eq("1de660471e79f834336526379fd76bebbcb69057f36237bdd82f8af58d9641de")
|
147
|
+
expect(Apes::UrlsParser.instance.hashify("http://bit.ly/1000")).to eq("1de660471e79f834336526379fd76bebbcb69057f36237bdd82f8af58d9641de")
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
#
|
2
|
+
# This file is part of the apes gem. Copyright (C) 2016 and above Shogun <shogun@cowtech.it>.
|
3
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
4
|
+
#
|
5
|
+
|
6
|
+
require "spec_helper"
|
7
|
+
|
8
|
+
describe Apes::Validators::BaseValidator do
|
9
|
+
class BaseMockValidationValidator < Apes::Validators::BaseValidator
|
10
|
+
def check_valid?(_)
|
11
|
+
false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class BaseMockModel
|
16
|
+
include ActiveModel::Validations
|
17
|
+
include Apes::Model
|
18
|
+
|
19
|
+
attr_reader :field, :other_field
|
20
|
+
validates :field, "base_mock_validation" => {message: "ERROR"}
|
21
|
+
validates :other_field, "base_mock_validation" => {default_message: "DEFAULT", additional: true}
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#validate_each" do
|
25
|
+
it "should correctly record messages" do
|
26
|
+
subject = BaseMockModel.new
|
27
|
+
subject.validate
|
28
|
+
expect(subject.errors.to_hash).to eq({field: ["ERROR"]})
|
29
|
+
expect(subject.additional_errors.to_hash).to eq({other_field: ["DEFAULT"]})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Apes::Validators::UuidValidator do
|
35
|
+
class UUIDMockModel
|
36
|
+
include ActiveModel::Validations
|
37
|
+
include Apes::Model
|
38
|
+
|
39
|
+
attr_accessor :field
|
40
|
+
validates :field, "apes/validators/uuid" => true
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#validate_each" do
|
44
|
+
it "should correctly validate fields" do
|
45
|
+
subject = UUIDMockModel.new
|
46
|
+
|
47
|
+
subject.field = "d250e78f-887a-4da2-8b4f-59f61c809bed"
|
48
|
+
subject.validate
|
49
|
+
expect(subject.errors.to_hash).to eq({})
|
50
|
+
|
51
|
+
subject.field = "100"
|
52
|
+
subject.validate
|
53
|
+
expect(subject.errors.to_hash).to eq({field: ["must be a valid UUID"]})
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe Apes::Validators::ReferenceValidator do
|
59
|
+
class ReferenceMockOtherModel
|
60
|
+
SECONDARY_QUERY = "name = :id"
|
61
|
+
end
|
62
|
+
|
63
|
+
class ReferenceMockModel
|
64
|
+
include ActiveModel::Validations
|
65
|
+
include Apes::Model
|
66
|
+
|
67
|
+
attr_accessor :field
|
68
|
+
validates :field, "apes/validators/reference" => {class_name: "reference_mock_other_model"}
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#validate_each" do
|
72
|
+
before(:each) do
|
73
|
+
allow(ReferenceMockOtherModel).to receive(:find_with_any).and_return(false)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should correctly validate fields" do
|
77
|
+
subject = ReferenceMockModel.new
|
78
|
+
subject.field = 100
|
79
|
+
subject.validate
|
80
|
+
expect(subject.errors.to_hash).to eq({field: ["must be a valid ReferenceMockOtherModel (cannot find a ReferenceMockOtherModel with id \"100\")"]})
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should correctly validate fields when they are array" do
|
84
|
+
subject = ReferenceMockModel.new
|
85
|
+
subject.field = [100, 101]
|
86
|
+
subject.validate
|
87
|
+
expect(subject.errors.to_hash).to eq({field: ["must be a valid ReferenceMockOtherModel (cannot find a ReferenceMockOtherModel with id \"100\")", "must be a valid ReferenceMockOtherModel (cannot find a ReferenceMockOtherModel with id \"101\")"]})
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe Apes::Validators::EmailValidator do
|
93
|
+
class EmailMockModel
|
94
|
+
include ActiveModel::Validations
|
95
|
+
include Apes::Model
|
96
|
+
|
97
|
+
attr_accessor :field
|
98
|
+
validates :field, "apes/validators/email" => true
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#validate_each" do
|
102
|
+
it "should correctly validate fields" do
|
103
|
+
subject = EmailMockModel.new
|
104
|
+
subject.field = 100
|
105
|
+
subject.validate
|
106
|
+
expect(subject.errors.to_hash).to eq({field: ["must be a valid email"]})
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe Apes::Validators::BooleanValidator do
|
112
|
+
class BooleanMockModel
|
113
|
+
include ActiveModel::Validations
|
114
|
+
include Apes::Model
|
115
|
+
|
116
|
+
attr_accessor :field
|
117
|
+
validates :field, "apes/validators/boolean" => true
|
118
|
+
end
|
119
|
+
|
120
|
+
describe ".parse" do
|
121
|
+
it "should correctly parse a value" do
|
122
|
+
expect(Apes::Validators::BooleanValidator.parse("YES")).to be_truthy
|
123
|
+
expect(Apes::Validators::BooleanValidator.parse("OTHER")).to be_falsey
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should raise errors if asked to" do
|
127
|
+
expect(Apes::Validators::BooleanValidator.parse(nil, raise_errors: true)).to be_falsey
|
128
|
+
expect { Apes::Validators::BooleanValidator.parse("", raise_errors: true) }.to raise_error(ArgumentError, "Invalid boolean value \"\".")
|
129
|
+
expect { Apes::Validators::BooleanValidator.parse("FOO", raise_errors: true) }.to raise_error(ArgumentError, "Invalid boolean value \"FOO\".")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "#validate_each" do
|
134
|
+
it "should correctly validate fields" do
|
135
|
+
subject = BooleanMockModel.new
|
136
|
+
subject.field = 100
|
137
|
+
subject.validate
|
138
|
+
expect(subject.errors.to_hash).to eq({field: ["must be a valid truthy/falsey value"]})
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe Apes::Validators::PhoneValidator do
|
144
|
+
class PhoneMockModel
|
145
|
+
include ActiveModel::Validations
|
146
|
+
include Apes::Model
|
147
|
+
|
148
|
+
attr_accessor :field
|
149
|
+
validates :field, "apes/validators/phone" => true
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "#validate_each" do
|
153
|
+
it "should correctly validate fields" do
|
154
|
+
subject = PhoneMockModel.new
|
155
|
+
|
156
|
+
subject.field = "+1 650-762-4637"
|
157
|
+
subject.validate
|
158
|
+
expect(subject.errors.to_hash).to eq({})
|
159
|
+
|
160
|
+
subject.field = "FOO"
|
161
|
+
subject.validate
|
162
|
+
expect(subject.errors.to_hash).to eq({field: ["must be a valid phone"]})
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe Apes::Validators::ZipCodeValidator do
|
168
|
+
class ZipCodeMockModel
|
169
|
+
include ActiveModel::Validations
|
170
|
+
include Apes::Model
|
171
|
+
|
172
|
+
attr_accessor :field
|
173
|
+
validates :field, "apes/validators/zip_code" => true
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "#validate_each" do
|
177
|
+
it "should correctly validate fields" do
|
178
|
+
subject = ZipCodeMockModel.new
|
179
|
+
|
180
|
+
subject.field = "12345"
|
181
|
+
subject.validate
|
182
|
+
expect(subject.errors.to_hash).to eq({})
|
183
|
+
|
184
|
+
subject.field = "12345-6789"
|
185
|
+
subject.validate
|
186
|
+
expect(subject.errors.to_hash).to eq({})
|
187
|
+
|
188
|
+
|
189
|
+
subject.field = "100"
|
190
|
+
subject.validate
|
191
|
+
expect(subject.errors.to_hash).to eq({field: ["must be a valid ZIP code"]})
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe Apes::Validators::TimestampValidator do
|
197
|
+
class TimestampMockModel
|
198
|
+
include ActiveModel::Validations
|
199
|
+
include Apes::Model
|
200
|
+
|
201
|
+
attr_accessor :field, :other_field
|
202
|
+
validates :field, "apes/validators/timestamp" => true
|
203
|
+
validates :other_field, "apes/validators/timestamp" => {formats: ["%Y"]}
|
204
|
+
end
|
205
|
+
|
206
|
+
describe ".parse" do
|
207
|
+
it "should parse respecting formats, using ISO-8601 formats by default" do
|
208
|
+
ISO8601 = "%FT%T%z".freeze
|
209
|
+
FULL_ISO8601 = "%FT%T.%L%z".freeze
|
210
|
+
|
211
|
+
allow(Apes::RuntimeConfiguration).to receive(:timestamp_formats).and_return({default: "%FT%T%z", full: "%FT%T.%L%z", clean: "%Y%m%dT%H%M%S.%L%z", clean_full: "%Y%m%dT%H%M%S.%L%z"})
|
212
|
+
expect(Apes::Validators::TimestampValidator.parse("2016-05-04T03:02:01+06:00")).to eq(DateTime.civil(2016, 5, 4, 3, 2, 1, "+6"))
|
213
|
+
expect(Apes::Validators::TimestampValidator.parse("2016-05-04T03:02:01.789-05:00")).to eq(DateTime.civil(2016, 5, 4, 3, 2, 1.789, "-5"))
|
214
|
+
expect(Apes::Validators::TimestampValidator.parse("2016-05-04")).to be_nil
|
215
|
+
expect(Apes::Validators::TimestampValidator.parse("2016-05-04+06:00", formats: ["%F%z"])).to eq(DateTime.civil(2016, 5, 4, 0, 0, 0, "+6"))
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should raise errors if asked to" do
|
219
|
+
expect { Apes::Validators::TimestampValidator.parse("2016-05-04", raise_errors: true) } .to raise_error(ArgumentError, "Invalid timestamp \"2016-05-04\".")
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe "#validate_each" do
|
224
|
+
it "should correctly validate fields" do
|
225
|
+
subject = TimestampMockModel.new
|
226
|
+
subject.field = 2016
|
227
|
+
subject.other_field = "xxxx"
|
228
|
+
subject.validate
|
229
|
+
expect(subject.errors.to_hash).to eq({field: ["must be a valid ISO 8601 timestamp"], other_field: ["must be a valid ISO 8601 timestamp"]})
|
230
|
+
|
231
|
+
subject.field = Time.now
|
232
|
+
subject.other_field = "2016"
|
233
|
+
subject.validate
|
234
|
+
expect(subject.errors.to_hash).to eq({})
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|