jdx-sinatra-param 0.0.1
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/Gemfile +3 -0
- data/LICENSE +19 -0
- data/README.md +182 -0
- data/Rakefile +18 -0
- data/example/Gemfile +4 -0
- data/example/Procfile +1 -0
- data/example/app.rb +52 -0
- data/example/config.ru +6 -0
- data/lib/sinatra/param.rb +199 -0
- data/lib/sinatra/param/version.rb +5 -0
- data/sinatra-param.gemspec +26 -0
- data/spec/dummy/app.rb +285 -0
- data/spec/parameter_conjunctivity_spec.rb +34 -0
- data/spec/parameter_exclusivity_spec.rb +55 -0
- data/spec/parameter_inclusivity_spec.rb +30 -0
- data/spec/parameter_raise_spec.rb +25 -0
- data/spec/parameter_spec.rb +19 -0
- data/spec/parameter_transformations_spec.rb +42 -0
- data/spec/parameter_type_coercion_spec.rb +202 -0
- data/spec/parameter_validations_spec.rb +216 -0
- data/spec/spec_helper.rb +20 -0
- metadata +144 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Parameter' do
|
4
|
+
it 'only sets parameters present in request or with a default value' do
|
5
|
+
get('/', a: 'a', b: 'b') do |response|
|
6
|
+
response_body = JSON.parse(response.body)
|
7
|
+
expect(response_body).to be_member('a')
|
8
|
+
expect(response_body).to be_member('b')
|
9
|
+
expect(response_body).to be_member('c')
|
10
|
+
expect(response_body).to_not be_member('d')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'stringifies parameters' do
|
15
|
+
get('/keys/stringify', q: 'test') do |response|
|
16
|
+
expect(response.body).to eq 'TEST'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Parameter Transformations' do
|
4
|
+
describe 'default' do
|
5
|
+
it 'sets a default value when none is given' do
|
6
|
+
get('/default') do |response|
|
7
|
+
expect(response.status).to eql 200
|
8
|
+
expect(JSON.parse(response.body)['sort']).to eql 'title'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'sets a default value from an empty hash' do
|
13
|
+
get('/default/hash') do |response|
|
14
|
+
expect(response.status).to eql 200
|
15
|
+
expect(JSON.parse(response.body)['attributes']).to eql Hash.new
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'sets a default value from a proc' do
|
20
|
+
get('/default/proc') do |response|
|
21
|
+
expect(response.status).to eql 200
|
22
|
+
expect(JSON.parse(response.body)['year']).to eql 2014
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'transform' do
|
28
|
+
it 'transforms the input using to_proc' do
|
29
|
+
get('/transform', order: 'asc') do |response|
|
30
|
+
expect(response.status).to eql 200
|
31
|
+
expect(JSON.parse(response.body)['order']).to eql 'ASC'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'skips transformations when the value is nil' do
|
36
|
+
get('/transform/required') do |response|
|
37
|
+
expect(response.status).to eql 400
|
38
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter is required")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Parameter Types' do
|
4
|
+
describe 'String' do
|
5
|
+
it 'coerces strings' do
|
6
|
+
get('/coerce/string', arg: '1234') do |response|
|
7
|
+
expect(response.status).to eql 200
|
8
|
+
expect(JSON.parse(response.body)['arg']).to eq('1234')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'Integer' do
|
14
|
+
it 'coerces integers' do
|
15
|
+
get('/coerce/integer', arg: '1234') do |response|
|
16
|
+
expect(response.status).to eql 200
|
17
|
+
expect(JSON.parse(response.body)['arg']).to eq(1234)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns 400 on requests when integer is invalid' do
|
22
|
+
get('/coerce/integer', arg: '123abc') do |response|
|
23
|
+
expect(response.status).to eql 400
|
24
|
+
expect(JSON.parse(response.body)['message']).to eq("'123abc' is not a valid Integer")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'Float' do
|
30
|
+
it 'coerces floats' do
|
31
|
+
get('/coerce/float', arg: '1234') do |response|
|
32
|
+
expect(response.status).to eql 200
|
33
|
+
expect(JSON.parse(response.body)['arg']).to eq(1234.0)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns 400 on requests when float is invalid' do
|
38
|
+
get('/coerce/float', arg: '123abc') do |response|
|
39
|
+
expect(response.status).to eql 400
|
40
|
+
expect(JSON.parse(response.body)['message']).to eq("'123abc' is not a valid Float")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'Time' do
|
46
|
+
it 'coerces time' do
|
47
|
+
get('/coerce/time', arg: '20130117') do |response|
|
48
|
+
expect(response.status).to eql 200
|
49
|
+
expect(JSON.parse(response.body)['arg']).to match(/2013-01-17 00:00:00/)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns 400 on requests when time is invalid' do
|
54
|
+
get('/coerce/time', arg: 'noon') do |response|
|
55
|
+
expect(response.status).to eql 400
|
56
|
+
expect(JSON.parse(response.body)['message']).to eq("'noon' is not a valid Time")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'Date' do
|
62
|
+
it 'coerces date' do
|
63
|
+
get('/coerce/date', arg: '20130117') do |response|
|
64
|
+
expect(response.status).to eql 200
|
65
|
+
expect(JSON.parse(response.body)['arg']).to eq('2013-01-17')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'returns 400 on requests when date is invalid' do
|
70
|
+
get('/coerce/date', arg: 'abc') do |response|
|
71
|
+
expect(response.status).to eql 400
|
72
|
+
expect(JSON.parse(response.body)['message']).to eq("'abc' is not a valid Date")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'DateTime' do
|
78
|
+
it 'coerces datetimes' do
|
79
|
+
get('/coerce/datetime', arg: '20130117') do |response|
|
80
|
+
expect(response.status).to eql 200
|
81
|
+
expect(JSON.parse(response.body)['arg']).to eq('2013-01-17T00:00:00+00:00')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'returns 400 on requests when datetime is invalid' do
|
86
|
+
get('/coerce/datetime', arg: 'abc') do |response|
|
87
|
+
expect(response.status).to eql 400
|
88
|
+
expect(JSON.parse(response.body)['message']).to eq("'abc' is not a valid DateTime")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'Array' do
|
94
|
+
it 'coerces arrays' do
|
95
|
+
get('/coerce/array', arg: '1,2,3,4,5') do |response|
|
96
|
+
expect(response.status).to eql 200
|
97
|
+
parsed_body = JSON.parse(response.body)
|
98
|
+
expect(parsed_body['arg']).to be_an(Array)
|
99
|
+
expect(parsed_body['arg']).to eq(%w(1 2 3 4 5))
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'coerces arrays of size 1' do
|
104
|
+
get('/coerce/array', arg: '1') do |response|
|
105
|
+
expect(response.status).to eql 200
|
106
|
+
parsed_body = JSON.parse(response.body)
|
107
|
+
expect(parsed_body['arg']).to be_an(Array)
|
108
|
+
expect(parsed_body['arg']).to eq(%w(1))
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'coerces arrays with arg[] style' do
|
113
|
+
get('/coerce/array', 'arg[]' => ['1','2','3','4','5']) do |response|
|
114
|
+
expect(response.status).to eql 200
|
115
|
+
parsed_body = JSON.parse(response.body)
|
116
|
+
expect(parsed_body['arg']).to be_an(Array)
|
117
|
+
expect(parsed_body['arg']).to eq(%w(1 2 3 4 5))
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe 'Hash' do
|
123
|
+
it 'coerces hashes' do
|
124
|
+
get('/coerce/hash', arg: 'a:b,c:d') do |response|
|
125
|
+
expect(response.status).to eql 200
|
126
|
+
parsed_body = JSON.parse(response.body)
|
127
|
+
expect(parsed_body['arg']).to be_an(Hash)
|
128
|
+
expect(parsed_body['arg']).to eq({ 'a' => 'b', 'c' => 'd'})
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe 'Boolean' do
|
134
|
+
it 'coerces truthy booleans to true' do
|
135
|
+
%w(1 true t yes y).each do |bool|
|
136
|
+
get('/coerce/boolean', arg: bool) do |response|
|
137
|
+
expect(response.status).to eql 200
|
138
|
+
expect(JSON.parse(response.body)['arg']).to be true
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'coerces falsey booleans to false' do
|
144
|
+
%w(0 false f no n).each do |bool|
|
145
|
+
get('/coerce/boolean', arg: bool) do |response|
|
146
|
+
expect(response.status).to eql 200
|
147
|
+
expect(JSON.parse(response.body)['arg']).to be false
|
148
|
+
expect(JSON.parse(response.body)['arg']).to_not be_nil
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'coerces truthy booleans to true when default is false' do
|
154
|
+
%w(1 true t yes y).each do |bool|
|
155
|
+
get('/default/boolean/false', arg: bool) do |response|
|
156
|
+
expect(response.status).to eql 200
|
157
|
+
expect(JSON.parse(response.body)['arg']).to be true
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'coerces falsey booleans to false when default is true' do
|
163
|
+
%w(0 false f no n).each do |bool|
|
164
|
+
get('/default/boolean/true', arg: bool) do |response|
|
165
|
+
expect(response.status).to eql 200
|
166
|
+
expect(JSON.parse(response.body)['arg']).to be false
|
167
|
+
expect(JSON.parse(response.body)['arg']).to_not be_nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'coerces default booleans to true when default is true and its not provided' do
|
173
|
+
get('/default/boolean/true') do |response|
|
174
|
+
expect(response.status).to eql 200
|
175
|
+
expect(JSON.parse(response.body)['arg']).to be true
|
176
|
+
expect(JSON.parse(response.body)['arg']).to_not be_nil
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'coerces default booleans to false when default is false and its not provided' do
|
181
|
+
get('/default/boolean/false') do |response|
|
182
|
+
expect(response.status).to eql 200
|
183
|
+
expect(JSON.parse(response.body)['arg']).to be false
|
184
|
+
expect(JSON.parse(response.body)['arg']).to_not be_nil
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'returns 400 on requests when true is not a truthy value' do
|
189
|
+
get('/default/boolean/true', arg: 'abc') do |response|
|
190
|
+
expect(response.status).to eql 400
|
191
|
+
expect(JSON.parse(response.body)['message']).to eq("'abc' is not a valid boolean")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'returns 400 on requests when false is not a falsey value' do
|
196
|
+
get('/default/boolean/false', arg: 'abc') do |response|
|
197
|
+
expect(response.status).to eql 400
|
198
|
+
expect(JSON.parse(response.body)['message']).to eq("'abc' is not a valid boolean")
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Parameter Validations' do
|
4
|
+
describe 'required' do
|
5
|
+
it 'returns 400 on requests without required fields' do
|
6
|
+
get('/validation/required') do |response|
|
7
|
+
expect(response.status).to eq(400)
|
8
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter is required")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns 200 on requests when required field present' do
|
13
|
+
get('/validation/required', arg: 'foo') do |response|
|
14
|
+
expect(response.status).to eq(200)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'blank' do
|
20
|
+
it 'returns 400 on requests when string is blank' do
|
21
|
+
get('/validation/blank/string', arg: '') do |response|
|
22
|
+
expect(response.status).to eq(400)
|
23
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter cannot be blank")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns 400 on requests when array is blank' do
|
28
|
+
get('/validation/blank/array', arg: '') do |response|
|
29
|
+
expect(response.status).to eq(400)
|
30
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter cannot be blank")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns 400 on requests when hash is blank' do
|
35
|
+
get('/validation/blank/hash', arg: '') do |response|
|
36
|
+
expect(response.status).to eq(400)
|
37
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter cannot be blank")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'returns 400 on requests when hash is blank' do
|
42
|
+
get('/validation/blank/other', arg: '') do |response|
|
43
|
+
expect(response.status).to eq(400)
|
44
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter cannot be blank")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'returns 200 on request when blank is true' do
|
49
|
+
get('/validation/nonblank/string', arg: '') do |response|
|
50
|
+
expect(response.status).to eq(200)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'format' do
|
56
|
+
it 'returns 200 on requests when value matches the param regex' do
|
57
|
+
get('/validation/format/hello', arg: 'hello world') do |response|
|
58
|
+
expect(response.status).to eq(200)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns 400 on requests when value does not match the param regex' do
|
63
|
+
get('/validation/format/hello', arg: 'world') do |response|
|
64
|
+
expect(response.status).to eq(400)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'returns 400 on requests when value is not a string' do
|
69
|
+
get('/validation/format/9000', arg: 9000) do |response|
|
70
|
+
expect(response.status).to eq(400)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'is' do
|
76
|
+
it 'returns 400 on requests when value is other than defined' do
|
77
|
+
get('/validation/is', arg: 'bar') do |response|
|
78
|
+
expect(response.status).to eq(400)
|
79
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter must be foo")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'returns 200 on requests with a value is other than defined' do
|
84
|
+
get('/validation/is', arg: 'foo') do |response|
|
85
|
+
expect(response.status).to eq(200)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'in' do
|
91
|
+
it 'returns 400 on requests with a value not in the set' do
|
92
|
+
get('/validation/in', arg: 'MISC') do |response|
|
93
|
+
expect(response.status).to eq(400)
|
94
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter must be within [\"ASC\", \"DESC\"]")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'returns 200 on requests with a value in the set' do
|
99
|
+
get('/validation/in', arg: 'ASC') do |response|
|
100
|
+
expect(response.status).to eq(200)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe 'within' do
|
106
|
+
it 'returns 400 on requests with a value outside the range' do
|
107
|
+
get('/validation/within', arg: 20) do |response|
|
108
|
+
expect(response.status).to eq(400)
|
109
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter must be within 1..10")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'returns 200 on requests with a value within the range' do
|
114
|
+
get('/validation/within', arg: 5) do |response|
|
115
|
+
expect(response.status).to eq(200)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe 'range' do
|
121
|
+
it 'returns 400 on requests with a value outside the range' do
|
122
|
+
get('/validation/range', arg: 20) do |response|
|
123
|
+
expect(response.status).to eq(400)
|
124
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter must be within 1..10")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'returns 200 on requests within the range' do
|
129
|
+
get('/validation/range', arg: 10) do |response|
|
130
|
+
expect(response.status).to eq(200)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe 'min' do
|
136
|
+
it 'returns 400 on requests with a value smaller than min' do
|
137
|
+
get('/validation/min', arg: 5) do |response|
|
138
|
+
expect(response.status).to eq(400)
|
139
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter cannot be less than 12")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'returns 200 on requests with a value larger than min' do
|
144
|
+
get('/validation/min', arg: 200) do |response|
|
145
|
+
expect(response.status).to eq(200)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe 'max' do
|
151
|
+
it 'returns 400 on requests with a value larger than max' do
|
152
|
+
get('/validation/max', arg: 100) do |response|
|
153
|
+
expect(response.status).to eq(400)
|
154
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter cannot be greater than 20")
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'returns 200 on requests with a value smaller than max' do
|
159
|
+
get('/validation/max', arg: 2) do |response|
|
160
|
+
expect(response.status).to eq(200)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe 'min_length' do
|
166
|
+
it 'returns 400 on requests with a string shorter than min_length' do
|
167
|
+
get('/validation/min_length', arg: 'hi') do |response|
|
168
|
+
expect(response.status).to eq(400)
|
169
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter cannot have length less than 5")
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'returns 200 on requests with a string longer than min_length' do
|
174
|
+
get('/validation/max_length', arg: 'longer') do |response|
|
175
|
+
expect(response.status).to eq(200)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe 'max_length' do
|
181
|
+
it 'returns 400 on requests with a string longer than max_length' do
|
182
|
+
get('/validation/max_length', arg: 'reallylongstringlongerthanmax') do |response|
|
183
|
+
expect(response.status).to eq(400)
|
184
|
+
expect(JSON.parse(response.body)['message']).to eq("Parameter cannot have length greater than 10")
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'returns 200 on requests with a string shorter than max_length' do
|
189
|
+
get('/validation/max_length', arg: 'short') do |response|
|
190
|
+
expect(response.status).to eq(200)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context 'content-type header' do
|
196
|
+
it 'returns application/json for JSON APIs' do
|
197
|
+
get('/validation/max_length', arg: 'reallylongstringlongerthanmax') do |response|
|
198
|
+
expect(response.headers['Content-Type']).to eq('application/json')
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'returns text/plain for non-JSON APIs' do
|
203
|
+
get('/xml', arg: 'reallylongstringlongerthanmax') do |response|
|
204
|
+
expect(response.headers['Content-Type']).to include('text/plain')
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context 'custom message ' do
|
210
|
+
it 'returns a custom message when configured' do
|
211
|
+
get('/custommessage') do |response|
|
212
|
+
expect(JSON.parse(response.body)['message']).to eq("'a' must be less than 10")
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|