apes 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|