input_sanitizer 0.1.9 → 0.4.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/.github/workflows/gempush.yml +28 -0
- data/.gitignore +2 -1
- data/.travis.yml +4 -8
- data/CHANGELOG +96 -0
- data/LICENSE +201 -22
- data/README.md +22 -3
- data/input_sanitizer.gemspec +10 -4
- data/lib/input_sanitizer.rb +5 -2
- data/lib/input_sanitizer/errors.rb +142 -0
- data/lib/input_sanitizer/extended_converters.rb +5 -52
- data/lib/input_sanitizer/extended_converters/comma_joined_integers_converter.rb +15 -0
- data/lib/input_sanitizer/extended_converters/comma_joined_strings_converter.rb +15 -0
- data/lib/input_sanitizer/extended_converters/positive_integer_converter.rb +12 -0
- data/lib/input_sanitizer/extended_converters/specific_values_converter.rb +19 -0
- data/lib/input_sanitizer/restricted_hash.rb +49 -8
- data/lib/input_sanitizer/v1.rb +22 -0
- data/lib/input_sanitizer/v1/clean_field.rb +38 -0
- data/lib/input_sanitizer/{default_converters.rb → v1/default_converters.rb} +30 -13
- data/lib/input_sanitizer/v1/sanitizer.rb +166 -0
- data/lib/input_sanitizer/v2.rb +13 -0
- data/lib/input_sanitizer/v2/clean_field.rb +36 -0
- data/lib/input_sanitizer/v2/clean_payload_collection_field.rb +41 -0
- data/lib/input_sanitizer/v2/clean_query_collection_field.rb +40 -0
- data/lib/input_sanitizer/v2/error_collection.rb +49 -0
- data/lib/input_sanitizer/v2/nested_sanitizer_factory.rb +19 -0
- data/lib/input_sanitizer/v2/payload_sanitizer.rb +130 -0
- data/lib/input_sanitizer/v2/payload_transform.rb +42 -0
- data/lib/input_sanitizer/v2/query_sanitizer.rb +33 -0
- data/lib/input_sanitizer/v2/types.rb +213 -0
- data/lib/input_sanitizer/version.rb +1 -1
- data/spec/extended_converters/comma_joined_integers_converter_spec.rb +18 -0
- data/spec/extended_converters/comma_joined_strings_converter_spec.rb +18 -0
- data/spec/extended_converters/positive_integer_converter_spec.rb +18 -0
- data/spec/extended_converters/specific_values_converter_spec.rb +27 -0
- data/spec/restricted_hash_spec.rb +37 -7
- data/spec/sanitizer_spec.rb +129 -26
- data/spec/spec_helper.rb +17 -2
- data/spec/v1/default_converters_spec.rb +141 -0
- data/spec/v2/converters_spec.rb +174 -0
- data/spec/v2/payload_sanitizer_spec.rb +460 -0
- data/spec/v2/payload_transform_spec.rb +98 -0
- data/spec/v2/query_sanitizer_spec.rb +300 -0
- data/v2.md +52 -0
- metadata +105 -40
- data/lib/input_sanitizer/sanitizer.rb +0 -152
- data/spec/default_converters_spec.rb +0 -101
- data/spec/extended_converters_spec.rb +0 -62
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,22 @@
|
|
1
1
|
require 'bundler'
|
2
2
|
Bundler.setup(:test)
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
skip_coverage = ENV['CI']
|
5
|
+
|
6
|
+
unless skip_coverage
|
7
|
+
require 'simplecov'
|
8
|
+
SimpleCov.start
|
9
|
+
end
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.expect_with :rspec do |c|
|
13
|
+
c.syntax = :should
|
14
|
+
end
|
15
|
+
|
16
|
+
config.mock_with :rspec do |c|
|
17
|
+
c.syntax = :should
|
18
|
+
end
|
19
|
+
end
|
6
20
|
|
7
21
|
require 'input_sanitizer'
|
22
|
+
require 'pry'
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe InputSanitizer::V1::IntegerConverter do
|
4
|
+
let(:converter) { InputSanitizer::V1::IntegerConverter.new }
|
5
|
+
|
6
|
+
it "casts string to integer" do
|
7
|
+
converter.call("42").should == 42
|
8
|
+
end
|
9
|
+
|
10
|
+
it "casts integer to integer" do
|
11
|
+
converter.call(42).should == 42
|
12
|
+
end
|
13
|
+
|
14
|
+
it "raises error if cannot cast" do
|
15
|
+
lambda { converter.call("f") }.should raise_error(InputSanitizer::ConversionError)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe InputSanitizer::V1::DateConverter do
|
20
|
+
let(:converter) { InputSanitizer::V1::DateConverter.new }
|
21
|
+
|
22
|
+
it "casts dates in iso format" do
|
23
|
+
converter.call("2012-05-15").should == Date.new(2012, 5, 15)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "raises error if cannot cast" do
|
27
|
+
lambda { converter.call("2012-02-30") }.should raise_error(InputSanitizer::ConversionError)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe InputSanitizer::V1::BooleanConverter do
|
32
|
+
let(:converter) { InputSanitizer::V1::BooleanConverter.new }
|
33
|
+
|
34
|
+
it "casts 'true' to true" do
|
35
|
+
converter.call('true').should eq(true)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "casts true to true" do
|
39
|
+
converter.call(true).should eq(true)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "casts '1' to true" do
|
43
|
+
converter.call('1').should eq(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "casts 'yes' to true" do
|
47
|
+
converter.call('yes').should eq(true)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "casts 'false' to false" do
|
51
|
+
converter.call('false').should eq(false)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "casts false to false" do
|
55
|
+
converter.call(false).should eq(false)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "casts '0' to false" do
|
59
|
+
converter.call('0').should eq(false)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "casts 'no' to false" do
|
63
|
+
converter.call('no').should eq(false)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "raises error if cannot cast" do
|
67
|
+
lambda { converter.call("notboolean") }.should raise_error(InputSanitizer::ConversionError)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe InputSanitizer::V1::TimeConverter do
|
72
|
+
let(:converter) { InputSanitizer::V1::TimeConverter.new }
|
73
|
+
|
74
|
+
it "raises if timezone part given" do
|
75
|
+
lambda { converter.call("2012-05-15 13:42:54 +01:00") }.should raise_error(InputSanitizer::ConversionError)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "casts date time in iso format" do
|
79
|
+
t = Time.utc(2012, 5, 15, 13, 42, 54)
|
80
|
+
converter.call("2012-05-15 13:42:54").should == t
|
81
|
+
converter.call("2012-05-15T13:42:54").should == t
|
82
|
+
converter.call("20120515134254").should == t
|
83
|
+
end
|
84
|
+
|
85
|
+
it "works with miliseconds" do
|
86
|
+
t = Time.utc(2012, 5, 15, 13, 42, 54)
|
87
|
+
converter.call("2012-05-15 13:42:54.000").should == t
|
88
|
+
converter.call("2012-05-15T13:42:54.000").should == t
|
89
|
+
converter.call("20120515134254000").should == t
|
90
|
+
end
|
91
|
+
|
92
|
+
it "works with Z at the end" do
|
93
|
+
t = Time.utc(2012, 5, 15, 13, 42, 54)
|
94
|
+
converter.call("2012-05-15 13:42:54.000Z").should == t
|
95
|
+
converter.call("2012-05-15T13:42:54.000Z").should == t
|
96
|
+
converter.call("2012-05-15T13:42:54Z").should == t
|
97
|
+
converter.call("20120515134254000Z").should == t
|
98
|
+
end
|
99
|
+
|
100
|
+
it "does not require time part" do
|
101
|
+
converter.call("2012-05-15 13:42").should == Time.utc(2012, 5, 15, 13, 42)
|
102
|
+
converter.call("2012-05-15 13").should == Time.utc(2012, 5, 15, 13)
|
103
|
+
converter.call("2012-05-15").should == Time.utc(2012, 5, 15)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "raises error if can format is wrong" do
|
107
|
+
lambda { converter.call("2/10/2031 13:44:22") }.should raise_error(InputSanitizer::ConversionError)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "raises error if date is wrong" do
|
111
|
+
lambda { converter.call("2012-02-32") }.should raise_error(InputSanitizer::ConversionError)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "allows the instance of Time" do
|
115
|
+
t = Time.now
|
116
|
+
converter.call(t).should == t.utc
|
117
|
+
end
|
118
|
+
|
119
|
+
it "raises error if value is of invalid type" do
|
120
|
+
lambda { converter.call({}) }.should raise_error(InputSanitizer::ConversionError)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe InputSanitizer::V1::AllowNil do
|
125
|
+
it "passes blanks" do
|
126
|
+
lambda { |_| 1 }.extend(InputSanitizer::V1::AllowNil).call("").should be_nil
|
127
|
+
end
|
128
|
+
|
129
|
+
it "passes things the extended sanitizer passes" do
|
130
|
+
lambda { |_| :something }.extend(InputSanitizer::V1::AllowNil).call(:stuff).
|
131
|
+
should eq(:something)
|
132
|
+
end
|
133
|
+
|
134
|
+
it "raises error if the extended sanitizer raises error" do
|
135
|
+
action = lambda do
|
136
|
+
lambda { |_| raise "Some error" }.extend(InputSanitizer::V1::AllowNil).call(:stuff)
|
137
|
+
end
|
138
|
+
|
139
|
+
action.should raise_error
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# OPTIONS
|
4
|
+
# :allow_nil (default true)
|
5
|
+
# :allow_blank (default true)
|
6
|
+
# :require (default false, requires given key in params, and additionally sets :allow_nil and :allow_blank to false)
|
7
|
+
|
8
|
+
# | allow_nil | allow_blank
|
9
|
+
# __________|___________|_____________
|
10
|
+
# string | YES | YES
|
11
|
+
# url | YES | YES
|
12
|
+
# datetime | YES | YES
|
13
|
+
# integer | YES | NO
|
14
|
+
# boolean | NO | NO
|
15
|
+
# ------------------------------------
|
16
|
+
|
17
|
+
# [type, value, option] => valid? # if valid? == false then check for ValueMissing error
|
18
|
+
|
19
|
+
test_cases = {
|
20
|
+
[InputSanitizer::V2::Types::StringCheck, { :allow_nil => false }, nil] => false,
|
21
|
+
[InputSanitizer::V2::Types::StringCheck, { :allow_nil => false }, ""] => true,
|
22
|
+
[InputSanitizer::V2::Types::StringCheck, { :allow_nil => false }, "zz"] => true,
|
23
|
+
[InputSanitizer::V2::Types::StringCheck, { :allow_blank => false }, nil] => false,
|
24
|
+
[InputSanitizer::V2::Types::StringCheck, { :allow_blank => false }, ""] => false,
|
25
|
+
[InputSanitizer::V2::Types::StringCheck, { :allow_blank => false }, "zz"] => true,
|
26
|
+
[InputSanitizer::V2::Types::StringCheck, { :required => true }, nil] => false,
|
27
|
+
[InputSanitizer::V2::Types::StringCheck, { :required => true }, ""] => false,
|
28
|
+
[InputSanitizer::V2::Types::StringCheck, { :required => true }, "zz"] => true,
|
29
|
+
[InputSanitizer::V2::Types::StringCheck, { }, nil] => true,
|
30
|
+
[InputSanitizer::V2::Types::StringCheck, { }, ""] => true,
|
31
|
+
[InputSanitizer::V2::Types::StringCheck, { }, "zz"] => true,
|
32
|
+
[InputSanitizer::V2::Types::IntegerCheck, { :allow_nil => false }, nil] => false,
|
33
|
+
[InputSanitizer::V2::Types::IntegerCheck, { :allow_nil => false }, ""] => :invalid_type,
|
34
|
+
[InputSanitizer::V2::Types::IntegerCheck, { :allow_nil => false }, 1] => true,
|
35
|
+
[InputSanitizer::V2::Types::IntegerCheck, { :allow_blank => false }, nil] => false,
|
36
|
+
[InputSanitizer::V2::Types::IntegerCheck, { :allow_blank => false }, ""] => :invalid_type,
|
37
|
+
[InputSanitizer::V2::Types::IntegerCheck, { :allow_blank => false }, 1] => true,
|
38
|
+
[InputSanitizer::V2::Types::IntegerCheck, { :required => true }, nil] => false,
|
39
|
+
[InputSanitizer::V2::Types::IntegerCheck, { :required => true }, ""] => :invalid_type,
|
40
|
+
[InputSanitizer::V2::Types::IntegerCheck, { :required => true }, 1] => true,
|
41
|
+
[InputSanitizer::V2::Types::IntegerCheck, { }, nil] => true,
|
42
|
+
[InputSanitizer::V2::Types::IntegerCheck, { }, ""] => :invalid_type,
|
43
|
+
[InputSanitizer::V2::Types::IntegerCheck, { }, 1] => true,
|
44
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { :allow_nil => false }, nil] => false,
|
45
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { :allow_nil => false }, "null"] => false,
|
46
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { :allow_nil => false }, ""] => :invalid_type,
|
47
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { :allow_nil => false }, 1] => true,
|
48
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { :allow_blank => false }, nil] => false,
|
49
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { :allow_blank => false }, "null"] => false,
|
50
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { :allow_blank => false }, ""] => :invalid_type,
|
51
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { :allow_blank => false }, 1] => true,
|
52
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { :required => true }, nil] => false,
|
53
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { :required => true }, "null"] => false,
|
54
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { :required => true }, ""] => :invalid_type,
|
55
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { :required => true }, 1] => true,
|
56
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { }, nil] => true,
|
57
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { }, "null"] => true,
|
58
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { }, ""] => :invalid_type,
|
59
|
+
[InputSanitizer::V2::Types::CoercingIntegerCheck, { }, 1] => true,
|
60
|
+
[InputSanitizer::V2::Types::FloatCheck, { :allow_nil => false }, nil] => false,
|
61
|
+
[InputSanitizer::V2::Types::FloatCheck, { :allow_nil => false }, ""] => :invalid_type,
|
62
|
+
[InputSanitizer::V2::Types::FloatCheck, { :allow_nil => false }, 1] => true,
|
63
|
+
[InputSanitizer::V2::Types::FloatCheck, { :allow_nil => false }, 3.1415] => true,
|
64
|
+
[InputSanitizer::V2::Types::FloatCheck, { :allow_blank => false }, nil] => false,
|
65
|
+
[InputSanitizer::V2::Types::FloatCheck, { :allow_blank => false }, ""] => :invalid_type,
|
66
|
+
[InputSanitizer::V2::Types::FloatCheck, { :allow_blank => false }, 1] => true,
|
67
|
+
[InputSanitizer::V2::Types::FloatCheck, { :allow_blank => false }, 3.1415] => true,
|
68
|
+
[InputSanitizer::V2::Types::FloatCheck, { :required => true }, nil] => false,
|
69
|
+
[InputSanitizer::V2::Types::FloatCheck, { :required => true }, ""] => :invalid_type,
|
70
|
+
[InputSanitizer::V2::Types::FloatCheck, { :required => true }, 1] => true,
|
71
|
+
[InputSanitizer::V2::Types::FloatCheck, { :required => true }, 3.1415] => true,
|
72
|
+
[InputSanitizer::V2::Types::FloatCheck, { }, nil] => true,
|
73
|
+
[InputSanitizer::V2::Types::FloatCheck, { }, ""] => :invalid_type,
|
74
|
+
[InputSanitizer::V2::Types::FloatCheck, { }, 1] => true,
|
75
|
+
[InputSanitizer::V2::Types::FloatCheck, { }, 3.1415] => true,
|
76
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :allow_nil => false }, nil] => false,
|
77
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :allow_nil => false }, "null"] => false,
|
78
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :allow_nil => false }, ""] => :invalid_type,
|
79
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :allow_nil => false }, 1] => true,
|
80
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :allow_nil => false }, 3.1415] => true,
|
81
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :allow_nil => false }, "3.1415"] => true,
|
82
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :allow_blank => false }, nil] => false,
|
83
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :allow_blank => false }, "null"] => false,
|
84
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :allow_blank => false }, ""] => :invalid_type,
|
85
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :allow_blank => false }, 1] => true,
|
86
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :allow_blank => false }, 3.1415] => true,
|
87
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :allow_blank => false }, "3.1415"] => true,
|
88
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :required => true }, nil] => false,
|
89
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :required => true }, "null"] => false,
|
90
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :required => true }, ""] => :invalid_type,
|
91
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :required => true }, 1] => true,
|
92
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :required => true }, 3.1415] => true,
|
93
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { :required => true }, "3.1415"] => true,
|
94
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { }, nil] => true,
|
95
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { }, "null"] => true,
|
96
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { }, ""] => :invalid_type,
|
97
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { }, 1] => true,
|
98
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { }, 3.1415] => true,
|
99
|
+
[InputSanitizer::V2::Types::CoercingFloatCheck, { }, "3.1415"] => true,
|
100
|
+
[InputSanitizer::V2::Types::BooleanCheck, { :allow_nil => false }, nil] => false,
|
101
|
+
[InputSanitizer::V2::Types::BooleanCheck, { :allow_nil => false }, ""] => :invalid_type,
|
102
|
+
[InputSanitizer::V2::Types::BooleanCheck, { :allow_nil => false }, true] => true,
|
103
|
+
[InputSanitizer::V2::Types::BooleanCheck, { :allow_blank => false }, nil] => false,
|
104
|
+
[InputSanitizer::V2::Types::BooleanCheck, { :allow_blank => false }, ""] => :invalid_type,
|
105
|
+
[InputSanitizer::V2::Types::BooleanCheck, { :allow_blank => false }, true] => true,
|
106
|
+
[InputSanitizer::V2::Types::BooleanCheck, { :required => true }, nil] => false,
|
107
|
+
[InputSanitizer::V2::Types::BooleanCheck, { :required => true }, ""] => :invalid_type,
|
108
|
+
[InputSanitizer::V2::Types::BooleanCheck, { :required => true }, true] => true,
|
109
|
+
[InputSanitizer::V2::Types::BooleanCheck, { }, nil] => false,
|
110
|
+
[InputSanitizer::V2::Types::BooleanCheck, { }, ""] => :invalid_type,
|
111
|
+
[InputSanitizer::V2::Types::BooleanCheck, { }, true] => true,
|
112
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { :allow_nil => false }, nil] => false,
|
113
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { :allow_nil => false }, ""] => true,
|
114
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { :allow_nil => false }, "2014-08-27T16:32:56Z"] => true,
|
115
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { :allow_blank => false }, nil] => false,
|
116
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { :allow_blank => false }, ""] => false,
|
117
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { :allow_blank => false }, "2014-08-27T16:32:56Z"] => true,
|
118
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { :required => true }, nil] => false,
|
119
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { :required => true }, ""] => false,
|
120
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { :required => true }, "2014-08-27T16:32:56Z"] => true,
|
121
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { }, nil] => true,
|
122
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { }, ""] => true,
|
123
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { }, "2014-08-27T16:32:56Z"] => true,
|
124
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { }, 1234] => :invalid_type,
|
125
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { }, []] => :invalid_type,
|
126
|
+
[InputSanitizer::V2::Types::DatetimeCheck, { }, {}] => :invalid_type,
|
127
|
+
[InputSanitizer::V2::Types::URLCheck, { :allow_nil => false }, nil] => false,
|
128
|
+
[InputSanitizer::V2::Types::URLCheck, { :allow_nil => false }, ""] => true,
|
129
|
+
[InputSanitizer::V2::Types::URLCheck, { :allow_nil => false }, "http://getbase.com"] => true,
|
130
|
+
[InputSanitizer::V2::Types::URLCheck, { :allow_blank => false }, nil] => false,
|
131
|
+
[InputSanitizer::V2::Types::URLCheck, { :allow_blank => false }, ""] => false,
|
132
|
+
[InputSanitizer::V2::Types::URLCheck, { :allow_blank => false }, "http://getbase.com"] => true,
|
133
|
+
[InputSanitizer::V2::Types::URLCheck, { :required => true }, nil] => false,
|
134
|
+
[InputSanitizer::V2::Types::URLCheck, { :required => true }, ""] => false,
|
135
|
+
[InputSanitizer::V2::Types::URLCheck, { :required => true }, "http://getbase.com"] => true,
|
136
|
+
[InputSanitizer::V2::Types::URLCheck, { }, nil] => true,
|
137
|
+
[InputSanitizer::V2::Types::URLCheck, { }, ""] => true,
|
138
|
+
[InputSanitizer::V2::Types::URLCheck, { }, "http://getbase.com"] => true,
|
139
|
+
}
|
140
|
+
|
141
|
+
describe 'type checks' do
|
142
|
+
test_cases.each do |(test_case, result)|
|
143
|
+
describe test_case[0] do
|
144
|
+
context "with options: #{test_case[1]}" do
|
145
|
+
show_value = case test_case[2]
|
146
|
+
when nil then 'nil'
|
147
|
+
when '' then "''"
|
148
|
+
else "'#{test_case[2]}'"
|
149
|
+
end
|
150
|
+
|
151
|
+
it "correctly handles value #{show_value}" do
|
152
|
+
case result
|
153
|
+
when true
|
154
|
+
lambda { test_case[0].new.call(test_case[2], test_case[1]) }.should_not raise_error
|
155
|
+
when false
|
156
|
+
lambda { test_case[0].new.call(test_case[2], test_case[1]) }.should raise_error(InputSanitizer::BlankValueError)
|
157
|
+
when :invalid_type
|
158
|
+
lambda { test_case[0].new.call(test_case[2], test_case[1]) }.should raise_error(InputSanitizer::TypeMismatchError)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Generating test cases:
|
167
|
+
|
168
|
+
# types = ['string', 'integer', 'boolean', 'datetime', 'url']
|
169
|
+
# options = [:allow_nil_false, :allow_blank_false, :required_true, :no_params]
|
170
|
+
# values = [nil, '', lambda { |type| { 'string' => 'zz', 'integer' => 1, 'boolean' => true, 'datetime' => '2014-08-27T16:32:56Z', 'url' => 'http://getbase.com' }[type] }]
|
171
|
+
# test_cases = types.product(options).product(values).map(&:flatten).map! do |test_case|
|
172
|
+
# test_case[2] = test_case[2].call(test_case[0]) if test_case[2].is_a?(Proc); test_case
|
173
|
+
# end
|
174
|
+
# test_cases.each { |test_case| puts "#{test_case.inspect} => []," }; nil
|
@@ -0,0 +1,460 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class AddressSanitizer < InputSanitizer::V2::PayloadSanitizer
|
4
|
+
string :city
|
5
|
+
string :zip
|
6
|
+
end
|
7
|
+
|
8
|
+
class TagSanitizer < InputSanitizer::V2::PayloadSanitizer
|
9
|
+
integer :id
|
10
|
+
string :name
|
11
|
+
nested :addresses, :sanitizer => AddressSanitizer, :collection => true
|
12
|
+
end
|
13
|
+
|
14
|
+
class TestedPayloadSanitizer < InputSanitizer::V2::PayloadSanitizer
|
15
|
+
integer :array, :collection => true
|
16
|
+
integer :array_nil, :collection => true, :allow_nil => true
|
17
|
+
string :status, :allow => ['current', 'past']
|
18
|
+
string :status_with_empty, :allow => ['', 'current', 'past']
|
19
|
+
string :regexp_string, :regexp => /^#?([a-f0-9]{6}|[a-f0-9]{3})$/
|
20
|
+
nested :address, :sanitizer => AddressSanitizer
|
21
|
+
nested :nullable_address, :sanitizer => AddressSanitizer, :allow_nil => true
|
22
|
+
nested :tags, :sanitizer => TagSanitizer, :collection => true
|
23
|
+
|
24
|
+
float :float_attribute, :minimum => 1, :maximum => 100
|
25
|
+
integer :integer_attribute, :minimum => 1, :maximum => 100
|
26
|
+
string :string_attribute
|
27
|
+
boolean :bool_attribute
|
28
|
+
datetime :datetime_attribute
|
29
|
+
date :date_attribute, :minimum => Date.new(-2015, 01, 01), :maximum => Date.new(2015, 12, 31)
|
30
|
+
|
31
|
+
url :website
|
32
|
+
string :limited_collection, :collection => { :minimum => 1, :maximum => 2 }, :minimum => 2, :maximum => 12
|
33
|
+
string :allow_collection, :collection => true, :allow => ['yes', 'no']
|
34
|
+
end
|
35
|
+
|
36
|
+
class BlankValuesPayloadSanitizer < InputSanitizer::V2::PayloadSanitizer
|
37
|
+
string :required_string, :required => true
|
38
|
+
datetime :non_nil_datetime, :allow_nil => false
|
39
|
+
url :non_blank_url, :allow_blank => false
|
40
|
+
end
|
41
|
+
|
42
|
+
class CustomConverterWithProvidedValue < InputSanitizer::V2::PayloadSanitizer
|
43
|
+
integer :from
|
44
|
+
custom :to, :provide => :from, :converter => lambda { |value, options|
|
45
|
+
InputSanitizer::V2::Types::IntegerCheck.new.call(value)
|
46
|
+
raise InputSanitizer::ValueError.new(value, options[:provided][:from], nil) if options[:provided][:from] > value
|
47
|
+
value
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
describe InputSanitizer::V2::PayloadSanitizer do
|
52
|
+
let(:sanitizer) { TestedPayloadSanitizer.new(@params) }
|
53
|
+
let(:cleaned) { sanitizer.cleaned }
|
54
|
+
|
55
|
+
describe "collections" do
|
56
|
+
it "is invalid if collection is not an array" do
|
57
|
+
@params = { :array => {} }
|
58
|
+
sanitizer.should_not be_valid
|
59
|
+
end
|
60
|
+
|
61
|
+
it "is valid if collection is an array" do
|
62
|
+
@params = { :array => [] }
|
63
|
+
sanitizer.should be_valid
|
64
|
+
end
|
65
|
+
|
66
|
+
it "is valid if collection is an nil and allow_nil is passed" do
|
67
|
+
@params = { :array_nil => nil }
|
68
|
+
sanitizer.should be_valid
|
69
|
+
end
|
70
|
+
|
71
|
+
it "is invalid if there are too few elements" do
|
72
|
+
@params = { :limited_collection => [] }
|
73
|
+
sanitizer.should_not be_valid
|
74
|
+
end
|
75
|
+
|
76
|
+
it "is invalid if there are too many elements" do
|
77
|
+
@params = { :limited_collection => ['bear', 'bear', 'bear'] }
|
78
|
+
sanitizer.should_not be_valid
|
79
|
+
end
|
80
|
+
|
81
|
+
it "is valid when there are just enough elements" do
|
82
|
+
@params = { :limited_collection => ['goldilocks'] }
|
83
|
+
sanitizer.should be_valid
|
84
|
+
end
|
85
|
+
|
86
|
+
it "is invalid when any of the elements are too long" do
|
87
|
+
@params = { :limited_collection => ['more_than_the_limit'] }
|
88
|
+
sanitizer.should_not be_valid
|
89
|
+
end
|
90
|
+
|
91
|
+
it "is invalid when any of the elements are too short" do
|
92
|
+
@params = { :limited_collection => ['a'] }
|
93
|
+
sanitizer.should_not be_valid
|
94
|
+
end
|
95
|
+
|
96
|
+
it "is invalid when given disallowed value in a collection" do
|
97
|
+
@params = { :allow_collection => ['yes', 'no', 'whoa'] }
|
98
|
+
sanitizer.should_not be_valid
|
99
|
+
end
|
100
|
+
|
101
|
+
it "is valid when given allowed values in a collection" do
|
102
|
+
@params = { :allow_collection => ['yes', 'no'] }
|
103
|
+
sanitizer.should be_valid
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "allow option" do
|
108
|
+
it "is valid when given an allowed string" do
|
109
|
+
@params = { :status => 'past' }
|
110
|
+
sanitizer.should be_valid
|
111
|
+
end
|
112
|
+
|
113
|
+
it "is invalid when given an empty string" do
|
114
|
+
@params = { :status => '' }
|
115
|
+
sanitizer.should_not be_valid
|
116
|
+
sanitizer.errors[0].field.should eq('/status')
|
117
|
+
end
|
118
|
+
|
119
|
+
it "is valid when given an allowed empty string" do
|
120
|
+
@params = { :status_with_empty => '' }
|
121
|
+
sanitizer.should be_valid
|
122
|
+
end
|
123
|
+
|
124
|
+
it "is invalid when given a disallowed string" do
|
125
|
+
@params = { :status => 'current bad string' }
|
126
|
+
sanitizer.should_not be_valid
|
127
|
+
sanitizer.errors[0].field.should eq('/status')
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "minimum and maximum options" do
|
132
|
+
it "is invalid if integer is lower than the minimum" do
|
133
|
+
@params = { :integer_attribute => 0 }
|
134
|
+
sanitizer.should_not be_valid
|
135
|
+
end
|
136
|
+
|
137
|
+
it "is invalid if integer is greater than the maximum" do
|
138
|
+
@params = { :integer_attribute => 101 }
|
139
|
+
sanitizer.should_not be_valid
|
140
|
+
end
|
141
|
+
|
142
|
+
it "is valid when integer is within given range" do
|
143
|
+
@params = { :limited_collection => ['goldilocks'] }
|
144
|
+
sanitizer.should be_valid
|
145
|
+
end
|
146
|
+
|
147
|
+
it "is invalid if float is lower than the minimum" do
|
148
|
+
@params = { :float_attribute => 0.0 }
|
149
|
+
sanitizer.should_not be_valid
|
150
|
+
end
|
151
|
+
|
152
|
+
it "is invalid if float is greater than the maximum" do
|
153
|
+
@params = { :float_attribute => 101.0 }
|
154
|
+
sanitizer.should_not be_valid
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe "strict param checking" do
|
159
|
+
it "is invalid when given extra params" do
|
160
|
+
@params = { :extra => 'test', :extra2 => 1 }
|
161
|
+
sanitizer.should_not be_valid
|
162
|
+
sanitizer.errors.count.should eq(2)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "is invalid when given extra params in a nested sanitizer" do
|
166
|
+
@params = { :address => { :extra => 0 }, :tags => [ { :extra2 => 1 } ] }
|
167
|
+
sanitizer.should_not be_valid
|
168
|
+
sanitizer.errors.map(&:field).should contain_exactly('/address/extra', '/tags/0/extra2')
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "converters with provided values" do
|
173
|
+
let(:sanitizer) { CustomConverterWithProvidedValue.new(@params) }
|
174
|
+
|
175
|
+
it "is valid when converter passes check with provided value" do
|
176
|
+
@params = {from: 1, to: 3}
|
177
|
+
sanitizer.should be_valid
|
178
|
+
end
|
179
|
+
|
180
|
+
it "is invalid when converter does not pass check with provided value" do
|
181
|
+
@params = {from: 3, to: 1}
|
182
|
+
sanitizer.should_not be_valid
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe "strict type checking" do
|
187
|
+
it "is invalid when given string instead of integer" do
|
188
|
+
@params = { :integer_attribute => '1' }
|
189
|
+
sanitizer.should_not be_valid
|
190
|
+
sanitizer.errors[0].field.should eq('/integer_attribute')
|
191
|
+
end
|
192
|
+
|
193
|
+
it "is valid when given an integer" do
|
194
|
+
@params = { :integer_attribute => 50 }
|
195
|
+
sanitizer.should be_valid
|
196
|
+
sanitizer[:integer_attribute].should eq(50)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "is invalid when given a float" do
|
200
|
+
@params = { :integer_attribute => 50.99 }
|
201
|
+
sanitizer.should_not be_valid
|
202
|
+
end
|
203
|
+
|
204
|
+
it "is valid when given nil for an integer" do
|
205
|
+
@params = { :integer_attribute => nil }
|
206
|
+
sanitizer.should be_valid
|
207
|
+
sanitizer[:integer_attribute].should be_nil
|
208
|
+
end
|
209
|
+
|
210
|
+
it "is invalid when given string instead of float" do
|
211
|
+
@params = { :float_attribute => '1' }
|
212
|
+
sanitizer.should_not be_valid
|
213
|
+
sanitizer.errors[0].field.should eq('/float_attribute')
|
214
|
+
end
|
215
|
+
|
216
|
+
it "is valid when given a float" do
|
217
|
+
@params = { :float_attribute => 50.0 }
|
218
|
+
sanitizer.should be_valid
|
219
|
+
sanitizer[:float_attribute].should eq(50.0)
|
220
|
+
end
|
221
|
+
|
222
|
+
it "is valid when given nil for a float" do
|
223
|
+
@params = { :float_attribute => nil }
|
224
|
+
sanitizer.should be_valid
|
225
|
+
sanitizer[:float_attribute].should be_nil
|
226
|
+
end
|
227
|
+
|
228
|
+
it "is valid when given string is matching regexp" do
|
229
|
+
@params = { :regexp_string => "#8bd635" }
|
230
|
+
sanitizer.should be_valid
|
231
|
+
sanitizer[:regexp_string].should eq('#8bd635')
|
232
|
+
end
|
233
|
+
|
234
|
+
it "is invalid when given string is not matching regexp" do
|
235
|
+
@params = { :regexp_string => "not a hex value" }
|
236
|
+
sanitizer.should_not be_valid
|
237
|
+
sanitizer.errors[0].field.should eq('/regexp_string')
|
238
|
+
end
|
239
|
+
|
240
|
+
it "is invalid when given integer instead of string" do
|
241
|
+
@params = { :string_attribute => 0 }
|
242
|
+
sanitizer.should_not be_valid
|
243
|
+
sanitizer.errors[0].field.should eq('/string_attribute')
|
244
|
+
end
|
245
|
+
|
246
|
+
it "is invalid when given float instead of string" do
|
247
|
+
@params = { :string_attribute => 3.1415 }
|
248
|
+
sanitizer.should_not be_valid
|
249
|
+
sanitizer.errors[0].field.should eq('/string_attribute')
|
250
|
+
end
|
251
|
+
|
252
|
+
it "is valid when given a string" do
|
253
|
+
@params = { :string_attribute => '#@!#%#$@#ad' }
|
254
|
+
sanitizer.should be_valid
|
255
|
+
sanitizer[:string_attribute].should eq('#@!#%#$@#ad')
|
256
|
+
end
|
257
|
+
|
258
|
+
it "is invalid when given 'yes' as a bool" do
|
259
|
+
@params = { :bool_attribute => 'yes' }
|
260
|
+
sanitizer.should_not be_valid
|
261
|
+
sanitizer.errors[0].field.should eq('/bool_attribute')
|
262
|
+
end
|
263
|
+
|
264
|
+
it "is valid when given true as a bool" do
|
265
|
+
@params = { :bool_attribute => true }
|
266
|
+
sanitizer.should be_valid
|
267
|
+
end
|
268
|
+
|
269
|
+
it "is valid when given false as a bool" do
|
270
|
+
@params = { :bool_attribute => false }
|
271
|
+
sanitizer.should be_valid
|
272
|
+
end
|
273
|
+
|
274
|
+
it "is invalid when given an incorrect datetime" do
|
275
|
+
@params = { :datetime_attribute => "2014-08-2716:32:56Z" }
|
276
|
+
sanitizer.should_not be_valid
|
277
|
+
sanitizer.errors[0].field.should eq('/datetime_attribute')
|
278
|
+
end
|
279
|
+
|
280
|
+
it "is valid when given a correct datetime" do
|
281
|
+
@params = { :datetime_attribute => "2014-08-27T16:32:56Z" }
|
282
|
+
sanitizer.should be_valid
|
283
|
+
end
|
284
|
+
|
285
|
+
it "is valid when given a 'forever' timestamp" do
|
286
|
+
@params = { :datetime_attribute => "9999-12-31T00:00:00Z" }
|
287
|
+
sanitizer.should be_valid
|
288
|
+
end
|
289
|
+
|
290
|
+
it "is invalid when given an incorrect date" do
|
291
|
+
@params = { :date_attribute => "invalid" }
|
292
|
+
sanitizer.should_not be_valid
|
293
|
+
sanitizer.errors[0].field.should eq('/date_attribute')
|
294
|
+
end
|
295
|
+
|
296
|
+
it "is valid when given a correct date" do
|
297
|
+
@params = { :date_attribute => "2015-08-27" }
|
298
|
+
sanitizer.should be_valid
|
299
|
+
end
|
300
|
+
|
301
|
+
it "is valid when given a correct negative date" do
|
302
|
+
@params = { :date_attribute => "-2014-08-27" }
|
303
|
+
sanitizer.should be_valid
|
304
|
+
end
|
305
|
+
|
306
|
+
it "is valid when given a correct URL" do
|
307
|
+
@params = { :website => "https://google.com" }
|
308
|
+
sanitizer.should be_valid
|
309
|
+
sanitizer[:website].should eq("https://google.com")
|
310
|
+
end
|
311
|
+
|
312
|
+
it "is invalid when given an invalid URL" do
|
313
|
+
@params = { :website => "ht:/google.com" }
|
314
|
+
sanitizer.should_not be_valid
|
315
|
+
end
|
316
|
+
|
317
|
+
it "is invalid when given an invalid URL that contains a valid URL" do
|
318
|
+
@params = { :website => "watwat http://google.com wat" }
|
319
|
+
sanitizer.should_not be_valid
|
320
|
+
end
|
321
|
+
|
322
|
+
describe "blank and required values" do
|
323
|
+
let(:sanitizer) { BlankValuesPayloadSanitizer.new(@params) }
|
324
|
+
let(:defaults) { { :required_string => 'zz' } }
|
325
|
+
|
326
|
+
it "is invalid if required string is missing" do
|
327
|
+
@params = {}
|
328
|
+
sanitizer.should_not be_valid
|
329
|
+
sanitizer.errors[0].should be_an_instance_of(InputSanitizer::ValueMissingError)
|
330
|
+
sanitizer.errors[0].field.should eq('/required_string')
|
331
|
+
end
|
332
|
+
|
333
|
+
it "is invalid if required string is nil" do
|
334
|
+
@params = { :required_string => nil }
|
335
|
+
sanitizer.should_not be_valid
|
336
|
+
sanitizer.errors[0].should be_an_instance_of(InputSanitizer::BlankValueError)
|
337
|
+
sanitizer.errors[0].field.should eq('/required_string')
|
338
|
+
end
|
339
|
+
|
340
|
+
it "is invalid if required string is blank" do
|
341
|
+
@params = { :required_string => ' ' }
|
342
|
+
sanitizer.should_not be_valid
|
343
|
+
sanitizer.errors[0].should be_an_instance_of(InputSanitizer::BlankValueError)
|
344
|
+
sanitizer.errors[0].field.should eq('/required_string')
|
345
|
+
end
|
346
|
+
|
347
|
+
it "is invalid if non-nil datetime is null" do
|
348
|
+
@params = defaults.merge({ :non_nil_datetime => nil })
|
349
|
+
sanitizer.should_not be_valid
|
350
|
+
sanitizer.errors[0].should be_an_instance_of(InputSanitizer::BlankValueError)
|
351
|
+
sanitizer.errors[0].field.should eq('/non_nil_datetime')
|
352
|
+
end
|
353
|
+
|
354
|
+
it "is valid if non-nil datetime is blank" do
|
355
|
+
@params = defaults.merge({ :non_nil_datetime => '' })
|
356
|
+
sanitizer.should be_valid
|
357
|
+
end
|
358
|
+
|
359
|
+
it "is invalid if non-blank url is nil" do
|
360
|
+
@params = defaults.merge({ :non_blank_url => nil })
|
361
|
+
sanitizer.should_not be_valid
|
362
|
+
sanitizer.errors[0].should be_an_instance_of(InputSanitizer::BlankValueError)
|
363
|
+
sanitizer.errors[0].field.should eq('/non_blank_url')
|
364
|
+
end
|
365
|
+
|
366
|
+
it "is invalid if non-blank url is blank" do
|
367
|
+
@params = defaults.merge({ :non_blank_url => '' })
|
368
|
+
sanitizer.should_not be_valid
|
369
|
+
sanitizer.errors[0].should be_an_instance_of(InputSanitizer::BlankValueError)
|
370
|
+
sanitizer.errors[0].field.should eq('/non_blank_url')
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
describe "nested checking" do
|
375
|
+
describe "simple array" do
|
376
|
+
it "returns JSON pointer for invalid fields" do
|
377
|
+
@params = { :array => [1, 'z', '3', 4] }
|
378
|
+
sanitizer.errors.length.should eq(2)
|
379
|
+
sanitizer.errors.map(&:field).should contain_exactly('/array/1', '/array/2')
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
describe "nested object" do
|
384
|
+
it "returns an error when given a nil for a nested value" do
|
385
|
+
@params = { :address => nil }
|
386
|
+
sanitizer.should_not be_valid
|
387
|
+
end
|
388
|
+
|
389
|
+
it "returns an error when given a string for a nested value" do
|
390
|
+
@params = { :address => 'nope' }
|
391
|
+
sanitizer.should_not be_valid
|
392
|
+
end
|
393
|
+
|
394
|
+
it "returns an error when given an array for a nested value" do
|
395
|
+
@params = { :address => ['a'] }
|
396
|
+
sanitizer.should_not be_valid
|
397
|
+
end
|
398
|
+
|
399
|
+
it "returns JSON pointer for invalid fields" do
|
400
|
+
@params = { :address => { :city => 0, :zip => 1 } }
|
401
|
+
sanitizer.errors.length.should eq(2)
|
402
|
+
sanitizer.errors.map(&:field).should contain_exactly('/address/city', '/address/zip')
|
403
|
+
end
|
404
|
+
|
405
|
+
it "allows nil with `allow_nil` flag" do
|
406
|
+
@params = { :nullable_address => nil }
|
407
|
+
sanitizer.should be_valid
|
408
|
+
sanitizer.cleaned.fetch(:nullable_address).should eq(nil)
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
describe "array of nested objects" do
|
413
|
+
it "returns an error when given a nil for a collection" do
|
414
|
+
@params = { :tags => nil }
|
415
|
+
sanitizer.should_not be_valid
|
416
|
+
end
|
417
|
+
|
418
|
+
it "returns an error when given a string for a collection" do
|
419
|
+
@params = { :tags => 'nope' }
|
420
|
+
sanitizer.should_not be_valid
|
421
|
+
end
|
422
|
+
|
423
|
+
it "returns an error when given a hash for a collection" do
|
424
|
+
@params = { :tags => { :a => 1 } }
|
425
|
+
sanitizer.should_not be_valid
|
426
|
+
end
|
427
|
+
|
428
|
+
it "returns JSON pointer for invalid fields" do
|
429
|
+
@params = { :tags => [ { :id => 'n', :name => 1 }, { :id => 10, :name => 2 } ] }
|
430
|
+
sanitizer.errors.length.should eq(3)
|
431
|
+
sanitizer.errors.map(&:field).should contain_exactly(
|
432
|
+
'/tags/0/id',
|
433
|
+
'/tags/0/name',
|
434
|
+
'/tags/1/name'
|
435
|
+
)
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
describe "array of nested objects that have array of nested objects" do
|
440
|
+
it "returns JSON pointer for invalid fields" do
|
441
|
+
@params = { :tags => [
|
442
|
+
{ :id => 'n', :addresses => [ { :city => 0 }, { :city => 1 } ] },
|
443
|
+
{ :name => 2, :addresses => [ { :city => 3 } ] },
|
444
|
+
] }
|
445
|
+
sanitizer.errors.length.should eq(5)
|
446
|
+
sanitizer.errors.map(&:field).should contain_exactly(
|
447
|
+
'/tags/0/id',
|
448
|
+
'/tags/0/addresses/0/city',
|
449
|
+
'/tags/0/addresses/1/city',
|
450
|
+
'/tags/1/name',
|
451
|
+
'/tags/1/addresses/0/city'
|
452
|
+
)
|
453
|
+
|
454
|
+
ec = sanitizer.error_collection
|
455
|
+
ec.length.should eq(5)
|
456
|
+
end
|
457
|
+
end
|
458
|
+
end
|
459
|
+
end
|
460
|
+
end
|