roda 3.2.0 → 3.3.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 +4 -4
- data/CHANGELOG +4 -0
- data/README.rdoc +29 -1
- data/doc/release_notes/3.3.0.txt +291 -0
- data/lib/roda/plugins/class_matchers.rb +1 -1
- data/lib/roda/plugins/indifferent_params.rb +8 -1
- data/lib/roda/plugins/param_matchers.rb +11 -4
- data/lib/roda/plugins/path.rb +5 -2
- data/lib/roda/plugins/symbol_status.rb +2 -2
- data/lib/roda/plugins/typecast_params.rb +968 -0
- data/lib/roda/version.rb +1 -1
- data/spec/plugin/public_spec.rb +18 -0
- data/spec/plugin/typecast_params_spec.rb +1215 -0
- metadata +6 -2
data/lib/roda/version.rb
CHANGED
data/spec/plugin/public_spec.rb
CHANGED
@@ -33,6 +33,24 @@ describe "public plugin" do
|
|
33
33
|
body('/about/_test.erb').must_equal File.read('spec/views/about/_test.erb')
|
34
34
|
end
|
35
35
|
|
36
|
+
it "keeps existing :root option if loaded a second time" do
|
37
|
+
app(:bare) do
|
38
|
+
plugin :public, :root=>'spec/views'
|
39
|
+
plugin :public
|
40
|
+
|
41
|
+
route do |r|
|
42
|
+
r.public
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
body('/about/_test.erb').must_equal File.read('spec/views/about/_test.erb')
|
47
|
+
end
|
48
|
+
|
49
|
+
it "assumes public directory as default :root option" do
|
50
|
+
app(:public){}
|
51
|
+
app.opts[:public_root].must_equal File.expand_path('public')
|
52
|
+
end
|
53
|
+
|
36
54
|
it "handles serving gzip files in gzip mode if client supports gzip" do
|
37
55
|
app(:bare) do
|
38
56
|
plugin :public, :root=>'spec/views', :gzip=>true
|
@@ -0,0 +1,1215 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
describe "typecast_params plugin" do
|
5
|
+
def tp(arg='a=1&b[]=2&b[]=3&c[d]=4&c[e]=5&f=&g[]=&h[i]=')
|
6
|
+
@tp.call(arg)
|
7
|
+
end
|
8
|
+
|
9
|
+
def error
|
10
|
+
yield
|
11
|
+
rescue @tp_error => e
|
12
|
+
e
|
13
|
+
end
|
14
|
+
|
15
|
+
before do
|
16
|
+
res = nil
|
17
|
+
app(:typecast_params) do |r|
|
18
|
+
res = typecast_params
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
@tp = lambda do |params|
|
23
|
+
req('QUERY_STRING'=>params, 'rack.input'=>StringIO.new)
|
24
|
+
res
|
25
|
+
end
|
26
|
+
|
27
|
+
@tp_error = Roda::RodaPlugins::TypecastParams::Error
|
28
|
+
end
|
29
|
+
|
30
|
+
it ".new should raise error if params is not a hash" do
|
31
|
+
lambda{Roda::RodaPlugins::TypecastParams::Params.new('a')}.must_raise @tp_error
|
32
|
+
end
|
33
|
+
|
34
|
+
it ".new should raise for non String/Array args passed to conversion method" do
|
35
|
+
lambda{tp.any({})}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
|
36
|
+
lambda{tp.any(Object.new)}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
|
37
|
+
lambda{tp.any(:a)}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
|
38
|
+
end
|
39
|
+
|
40
|
+
it "#present should return whether the key is in the obj if given String" do
|
41
|
+
tp.present?('a').must_equal true
|
42
|
+
tp.present?('b').must_equal true
|
43
|
+
tp.present?('c').must_equal true
|
44
|
+
tp.present?('d').must_equal false
|
45
|
+
end
|
46
|
+
|
47
|
+
it "#present should return whether all keys are in the obj if given an Array" do
|
48
|
+
tp.present?(%w'a b c').must_equal true
|
49
|
+
tp.present?(%w'a b c d').must_equal false
|
50
|
+
end
|
51
|
+
|
52
|
+
it "#present should raise if given an unexpected object" do
|
53
|
+
lambda{tp.present?(:a)}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
|
54
|
+
lambda{tp.present?([:a])}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
|
55
|
+
lambda{tp.present?([['a']])}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
|
56
|
+
end
|
57
|
+
|
58
|
+
it "conversion methods should only support one level deep array of keys" do
|
59
|
+
lambda{tp.any([['a']])}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
|
60
|
+
end
|
61
|
+
|
62
|
+
it "#any should not do any conversion" do
|
63
|
+
tp.any('a').must_equal '1'
|
64
|
+
tp.any('b').must_equal ["2", "3"]
|
65
|
+
tp.any('c').must_equal('d'=>'4', 'e'=>'5')
|
66
|
+
tp.any('d').must_be_nil
|
67
|
+
tp.any(%w'g h').must_equal([[''], {'i'=>''}])
|
68
|
+
|
69
|
+
tp.any!('a').must_equal '1'
|
70
|
+
tp.any!(%w'a').must_equal %w'1'
|
71
|
+
lambda{tp.any!('d')}.must_raise @tp_error
|
72
|
+
lambda{tp.any!(%w'd j')}.must_raise @tp_error
|
73
|
+
|
74
|
+
lambda{tp.array(:any, 'a')}.must_raise @tp_error
|
75
|
+
tp.array(:any, 'b').must_equal ["2", "3"]
|
76
|
+
lambda{tp.array(:any, 'c')}.must_raise @tp_error
|
77
|
+
tp.array(:any, 'd').must_be_nil
|
78
|
+
tp.array(:any, %w'g').must_equal([['']])
|
79
|
+
lambda{tp.array(:any, 'h')}.must_raise @tp_error
|
80
|
+
|
81
|
+
tp.array!(:any, 'b').must_equal ["2", "3"]
|
82
|
+
lambda{tp.array!(:any, 'd')}.must_raise @tp_error
|
83
|
+
tp.array!(:any, %w'g').must_equal([['']])
|
84
|
+
end
|
85
|
+
|
86
|
+
it "#str should require strings" do
|
87
|
+
tp.str('a').must_equal '1'
|
88
|
+
lambda{tp.str('b')}.must_raise @tp_error
|
89
|
+
lambda{tp.str('c')}.must_raise @tp_error
|
90
|
+
lambda{tp.str(%w'b c')}.must_raise @tp_error
|
91
|
+
tp.str('d').must_be_nil
|
92
|
+
tp.str('f').must_equal ''
|
93
|
+
lambda{tp.str('g')}.must_raise @tp_error
|
94
|
+
lambda{tp.str('h')}.must_raise @tp_error
|
95
|
+
|
96
|
+
tp.str!('a').must_equal '1'
|
97
|
+
lambda{tp.str!('d')}.must_raise @tp_error
|
98
|
+
tp.str!('f').must_equal ''
|
99
|
+
|
100
|
+
lambda{tp.array(:str, 'a')}.must_raise @tp_error
|
101
|
+
tp.array(:str, 'b').must_equal ["2", "3"]
|
102
|
+
lambda{tp.array(:str, 'c')}.must_raise @tp_error
|
103
|
+
tp.array(:str, 'd').must_be_nil
|
104
|
+
tp.array(:str, 'g').must_equal [""]
|
105
|
+
lambda{tp.array(:str, 'h')}.must_raise @tp_error
|
106
|
+
|
107
|
+
tp.array!(:str, 'b').must_equal ["2", "3"]
|
108
|
+
lambda{tp.array!(:str, 'd')}.must_raise @tp_error
|
109
|
+
tp.array!(:str, 'g').must_equal [""]
|
110
|
+
end
|
111
|
+
|
112
|
+
it "#nonempty_str should require nonempty strings" do
|
113
|
+
tp.nonempty_str('a').must_equal '1'
|
114
|
+
tp('a=%201').nonempty_str('a').must_equal ' 1'
|
115
|
+
tp('a=1%20').nonempty_str('a').must_equal '1 '
|
116
|
+
tp('a=%201%20').nonempty_str('a').must_equal ' 1 '
|
117
|
+
tp('a=%20').nonempty_str('a').must_be_nil
|
118
|
+
lambda{tp.nonempty_str('b')}.must_raise @tp_error
|
119
|
+
lambda{tp.nonempty_str('c')}.must_raise @tp_error
|
120
|
+
tp.nonempty_str('d').must_be_nil
|
121
|
+
tp.nonempty_str('f').must_be_nil
|
122
|
+
lambda{tp.nonempty_str('g')}.must_raise @tp_error
|
123
|
+
lambda{tp.nonempty_str('h')}.must_raise @tp_error
|
124
|
+
|
125
|
+
tp.nonempty_str!('a').must_equal '1'
|
126
|
+
lambda{tp.nonempty_str!('d')}.must_raise @tp_error
|
127
|
+
lambda{tp.nonempty_str!('f')}.must_raise @tp_error
|
128
|
+
|
129
|
+
lambda{tp.array(:nonempty_str, 'a')}.must_raise @tp_error
|
130
|
+
tp.array(:nonempty_str, 'b').must_equal ["2", "3"]
|
131
|
+
lambda{tp.array(:nonempty_str, 'c')}.must_raise @tp_error
|
132
|
+
tp.array(:nonempty_str, 'd').must_be_nil
|
133
|
+
tp.array(:nonempty_str, 'g').must_equal [nil]
|
134
|
+
lambda{tp.array(:nonempty_str, 'h')}.must_raise @tp_error
|
135
|
+
|
136
|
+
tp.array!(:nonempty_str, 'b').must_equal ["2", "3"]
|
137
|
+
lambda{tp.array!(:nonempty_str, 'd')}.must_raise @tp_error
|
138
|
+
lambda{tp.array!(:nonempty_str, 'g')}.must_raise @tp_error
|
139
|
+
end
|
140
|
+
|
141
|
+
it "#bool should convert to boolean" do
|
142
|
+
tp('a=0').bool('a').must_equal false
|
143
|
+
tp('a=f').bool('a').must_equal false
|
144
|
+
tp('a=false').bool('a').must_equal false
|
145
|
+
tp('a=FALSE').bool('a').must_equal false
|
146
|
+
tp('a=F').bool('a').must_equal false
|
147
|
+
tp('a=n').bool('a').must_equal false
|
148
|
+
tp('a=no').bool('a').must_equal false
|
149
|
+
tp('a=N').bool('a').must_equal false
|
150
|
+
tp('a=NO').bool('a').must_equal false
|
151
|
+
tp('a=off').bool('a').must_equal false
|
152
|
+
tp('a=OFF').bool('a').must_equal false
|
153
|
+
|
154
|
+
tp('a=1').bool('a').must_equal true
|
155
|
+
tp('a=t').bool('a').must_equal true
|
156
|
+
tp('a=true').bool('a').must_equal true
|
157
|
+
tp('a=TRUE').bool('a').must_equal true
|
158
|
+
tp('a=T').bool('a').must_equal true
|
159
|
+
tp('a=y').bool('a').must_equal true
|
160
|
+
tp('a=yes').bool('a').must_equal true
|
161
|
+
tp('a=Y').bool('a').must_equal true
|
162
|
+
tp('a=YES').bool('a').must_equal true
|
163
|
+
tp('a=on').bool('a').must_equal true
|
164
|
+
tp('a=ON').bool('a').must_equal true
|
165
|
+
|
166
|
+
tp.bool('a').must_equal true
|
167
|
+
lambda{tp.bool('b')}.must_raise @tp_error
|
168
|
+
lambda{tp.bool('c')}.must_raise @tp_error
|
169
|
+
tp.bool('d').must_be_nil
|
170
|
+
tp.bool('f').must_be_nil
|
171
|
+
|
172
|
+
tp.bool!('a').must_equal true
|
173
|
+
lambda{tp.bool!('d')}.must_raise @tp_error
|
174
|
+
lambda{tp.bool!('f')}.must_raise @tp_error
|
175
|
+
|
176
|
+
lambda{tp.array(:bool, 'a')}.must_raise @tp_error
|
177
|
+
tp('b[]=1&b[]=0').array(:bool, 'b').must_equal [true, false]
|
178
|
+
lambda{tp('b[]=1&b[]=a').array(:bool, 'b')}.must_raise @tp_error
|
179
|
+
lambda{tp.array(:bool, 'c')}.must_raise @tp_error
|
180
|
+
tp.array(:bool, 'd').must_be_nil
|
181
|
+
tp.array(:bool, 'g').must_equal [nil]
|
182
|
+
lambda{tp.array(:bool, 'h')}.must_raise @tp_error
|
183
|
+
|
184
|
+
tp('b[]=1&b[]=0').array!(:bool, 'b').must_equal [true, false]
|
185
|
+
lambda{tp.array!(:bool, 'd')}.must_raise @tp_error
|
186
|
+
lambda{tp.array!(:bool, 'g')}.must_raise @tp_error
|
187
|
+
end
|
188
|
+
|
189
|
+
it "#int should convert to integer" do
|
190
|
+
tp('a=-1').int('a').must_equal -1
|
191
|
+
tp('a=0').int('a').must_equal 0
|
192
|
+
tp('a=a').int('a').must_equal 0
|
193
|
+
tp.int('a').must_equal 1
|
194
|
+
tp.int('a').must_be_kind_of Integer
|
195
|
+
lambda{tp.int('b')}.must_raise @tp_error
|
196
|
+
lambda{tp.int('c')}.must_raise @tp_error
|
197
|
+
tp.int('d').must_be_nil
|
198
|
+
tp.int('f').must_be_nil
|
199
|
+
lambda{tp.int('g')}.must_raise @tp_error
|
200
|
+
lambda{tp.int('h')}.must_raise @tp_error
|
201
|
+
|
202
|
+
tp.int!('a').must_equal 1
|
203
|
+
lambda{tp.int!('d')}.must_raise @tp_error
|
204
|
+
lambda{tp.int!('f')}.must_raise @tp_error
|
205
|
+
|
206
|
+
lambda{tp.array(:int, 'a')}.must_raise @tp_error
|
207
|
+
tp.array(:int, 'b').must_equal [2, 3]
|
208
|
+
lambda{tp.array(:int, 'c')}.must_raise @tp_error
|
209
|
+
tp.array(:int, 'd').must_be_nil
|
210
|
+
tp.array(:int, 'g').must_equal [nil]
|
211
|
+
lambda{tp.array(:int, 'h')}.must_raise @tp_error
|
212
|
+
|
213
|
+
tp.array!(:int, 'b').must_equal [2, 3]
|
214
|
+
lambda{tp.array!(:int, 'd')}.must_raise @tp_error
|
215
|
+
lambda{tp.array!(:int, 'g')}.must_raise @tp_error
|
216
|
+
end
|
217
|
+
|
218
|
+
it "#pos_int should convert to positive integer" do
|
219
|
+
tp('a=-1').pos_int('a').must_be_nil
|
220
|
+
tp('a=0').pos_int('a').must_be_nil
|
221
|
+
tp('a=a').pos_int('a').must_be_nil
|
222
|
+
tp.pos_int('a').must_equal 1
|
223
|
+
tp.pos_int('a').must_be_kind_of Integer
|
224
|
+
lambda{tp.pos_int('b')}.must_raise @tp_error
|
225
|
+
lambda{tp.pos_int('c')}.must_raise @tp_error
|
226
|
+
tp.pos_int('d').must_be_nil
|
227
|
+
tp.pos_int('f').must_be_nil
|
228
|
+
lambda{tp.pos_int('g')}.must_raise @tp_error
|
229
|
+
lambda{tp.pos_int('h')}.must_raise @tp_error
|
230
|
+
|
231
|
+
lambda{tp('a=-1').pos_int!('a')}.must_raise @tp_error
|
232
|
+
lambda{tp('a=0').pos_int!('a')}.must_raise @tp_error
|
233
|
+
lambda{tp('a=a').pos_int!('a')}.must_raise @tp_error
|
234
|
+
tp.pos_int!('a').must_equal 1
|
235
|
+
lambda{tp.pos_int!('d')}.must_raise @tp_error
|
236
|
+
lambda{tp.pos_int!('f')}.must_raise @tp_error
|
237
|
+
|
238
|
+
lambda{tp.array(:pos_int, 'a')}.must_raise @tp_error
|
239
|
+
tp.array(:pos_int, 'b').must_equal [2, 3]
|
240
|
+
lambda{tp.array(:pos_int, 'c')}.must_raise @tp_error
|
241
|
+
tp.array(:pos_int, 'd').must_be_nil
|
242
|
+
tp.array(:pos_int, 'g').must_equal [nil]
|
243
|
+
lambda{tp.array(:pos_int, 'h')}.must_raise @tp_error
|
244
|
+
|
245
|
+
tp.array!(:pos_int, 'b').must_equal [2, 3]
|
246
|
+
lambda{tp.array!(:pos_int, 'd')}.must_raise @tp_error
|
247
|
+
lambda{tp.array!(:pos_int, 'g')}.must_raise @tp_error
|
248
|
+
end
|
249
|
+
|
250
|
+
it "#Integer should convert to integer strictly" do
|
251
|
+
tp('a=-1').Integer('a').must_equal -1
|
252
|
+
tp('a=0').Integer('a').must_equal 0
|
253
|
+
lambda{tp('a=a').Integer('a')}.must_raise @tp_error
|
254
|
+
tp.Integer('a').must_equal 1
|
255
|
+
tp.Integer('a').must_be_kind_of Integer
|
256
|
+
lambda{tp.Integer('b')}.must_raise @tp_error
|
257
|
+
lambda{tp.Integer('c')}.must_raise @tp_error
|
258
|
+
tp.Integer('d').must_be_nil
|
259
|
+
tp.Integer('f').must_be_nil
|
260
|
+
lambda{tp.Integer('g')}.must_raise @tp_error
|
261
|
+
lambda{tp.Integer('h')}.must_raise @tp_error
|
262
|
+
|
263
|
+
tp.Integer!('a').must_equal 1
|
264
|
+
lambda{tp.Integer!('d')}.must_raise @tp_error
|
265
|
+
lambda{tp.Integer!('f')}.must_raise @tp_error
|
266
|
+
|
267
|
+
lambda{tp.array(:Integer, 'a')}.must_raise @tp_error
|
268
|
+
tp.array(:Integer, 'b').must_equal [2, 3]
|
269
|
+
lambda{tp.array(:Integer, 'c')}.must_raise @tp_error
|
270
|
+
tp.array(:Integer, 'd').must_be_nil
|
271
|
+
tp.array(:Integer, 'g').must_equal [nil]
|
272
|
+
lambda{tp.array(:Integer, 'h')}.must_raise @tp_error
|
273
|
+
|
274
|
+
tp.array!(:Integer, 'b').must_equal [2, 3]
|
275
|
+
lambda{tp.array!(:Integer, 'd')}.must_raise @tp_error
|
276
|
+
lambda{tp.array!(:Integer, 'g')}.must_raise @tp_error
|
277
|
+
end
|
278
|
+
|
279
|
+
it "#float should convert to float" do
|
280
|
+
tp('a=-1').float('a').must_equal -1
|
281
|
+
tp('a=0').float('a').must_equal 0
|
282
|
+
tp('a=a').float('a').must_equal 0
|
283
|
+
tp.float('a').must_equal 1
|
284
|
+
tp.float('a').must_be_kind_of Float
|
285
|
+
lambda{tp.float('b')}.must_raise @tp_error
|
286
|
+
lambda{tp.float('c')}.must_raise @tp_error
|
287
|
+
tp.float('d').must_be_nil
|
288
|
+
tp.float('f').must_be_nil
|
289
|
+
lambda{tp.float('g')}.must_raise @tp_error
|
290
|
+
lambda{tp.float('h')}.must_raise @tp_error
|
291
|
+
|
292
|
+
tp.float!('a').must_equal 1
|
293
|
+
lambda{tp.float!('d')}.must_raise @tp_error
|
294
|
+
lambda{tp.float!('f')}.must_raise @tp_error
|
295
|
+
|
296
|
+
lambda{tp.array(:float, 'a')}.must_raise @tp_error
|
297
|
+
tp.array(:float, 'b').must_equal [2, 3]
|
298
|
+
lambda{tp.array(:float, 'c')}.must_raise @tp_error
|
299
|
+
tp.array(:float, 'd').must_be_nil
|
300
|
+
tp.array(:float, 'g').must_equal [nil]
|
301
|
+
lambda{tp.array(:float, 'h')}.must_raise @tp_error
|
302
|
+
|
303
|
+
tp.array!(:float, 'b').must_equal [2, 3]
|
304
|
+
lambda{tp.array!(:float, 'd')}.must_raise @tp_error
|
305
|
+
lambda{tp.array!(:float, 'g')}.must_raise @tp_error
|
306
|
+
end
|
307
|
+
|
308
|
+
it "#Float should convert to float strictly" do
|
309
|
+
tp('a=-1').Float('a').must_equal -1
|
310
|
+
tp('a=0').Float('a').must_equal 0
|
311
|
+
lambda{tp('a=a').Float('a')}.must_raise @tp_error
|
312
|
+
tp.Float('a').must_equal 1
|
313
|
+
tp.Float('a').must_be_kind_of Float
|
314
|
+
lambda{tp.Float('b')}.must_raise @tp_error
|
315
|
+
lambda{tp.Float('c')}.must_raise @tp_error
|
316
|
+
tp.Float('d').must_be_nil
|
317
|
+
tp.Float('f').must_be_nil
|
318
|
+
lambda{tp.Float('g')}.must_raise @tp_error
|
319
|
+
lambda{tp.Float('h')}.must_raise @tp_error
|
320
|
+
|
321
|
+
tp.Float!('a').must_equal 1
|
322
|
+
lambda{tp.Float!('d')}.must_raise @tp_error
|
323
|
+
lambda{tp.Float!('f')}.must_raise @tp_error
|
324
|
+
|
325
|
+
lambda{tp.array(:Float, 'a')}.must_raise @tp_error
|
326
|
+
tp.array(:Float, 'b').must_equal [2, 3]
|
327
|
+
lambda{tp.array(:Float, 'c')}.must_raise @tp_error
|
328
|
+
tp.array(:Float, 'd').must_be_nil
|
329
|
+
tp.array(:Float, 'g').must_equal [nil]
|
330
|
+
lambda{tp.array(:Float, 'h')}.must_raise @tp_error
|
331
|
+
|
332
|
+
tp.array!(:Float, 'b').must_equal [2, 3]
|
333
|
+
lambda{tp.array!(:Float, 'd')}.must_raise @tp_error
|
334
|
+
lambda{tp.array!(:Float, 'g')}.must_raise @tp_error
|
335
|
+
end
|
336
|
+
|
337
|
+
it "#Hash should require hashes" do
|
338
|
+
lambda{tp.Hash('a')}.must_raise @tp_error
|
339
|
+
lambda{tp.Hash('b')}.must_raise @tp_error
|
340
|
+
tp.Hash('c').must_equal('d'=>'4', 'e'=>'5')
|
341
|
+
tp.Hash('d').must_be_nil
|
342
|
+
lambda{tp.Hash('f')}.must_raise @tp_error
|
343
|
+
lambda{tp.Hash('g')}.must_raise @tp_error
|
344
|
+
tp.Hash('h').must_equal('i'=>'')
|
345
|
+
|
346
|
+
tp.Hash!('c').must_equal('d'=>'4', 'e'=>'5')
|
347
|
+
lambda{tp.Hash!('d')}.must_raise @tp_error
|
348
|
+
tp.Hash!('h').must_equal('i'=>'')
|
349
|
+
|
350
|
+
lambda{tp.array(:Hash, 'c')}.must_raise @tp_error
|
351
|
+
lambda{tp('a[][b]=2&a[]=3').array(:Hash, 'a')}.must_raise @tp_error
|
352
|
+
tp('a[][b]=2&a[][b]=3').array(:Hash, 'a').must_equal [{'b'=>'2'}, {'b'=>'3'}]
|
353
|
+
tp.array(:Hash, 'd').must_be_nil
|
354
|
+
|
355
|
+
tp('a[][b]=2&a[][b]=3').array!(:Hash, 'a').must_equal [{'b'=>'2'}, {'b'=>'3'}]
|
356
|
+
lambda{tp.array!(:Hash, 'd')}.must_raise @tp_error
|
357
|
+
end
|
358
|
+
|
359
|
+
it "#Date should parse strings into Date instances" do
|
360
|
+
tp('a=').date('a').must_be_nil
|
361
|
+
tp('a=2017-10-11').date('a').must_equal Date.new(2017, 10, 11)
|
362
|
+
tp('a=17/10/11').date('a').must_equal Date.new(2017, 10, 11)
|
363
|
+
lambda{tp.date('b')}.must_raise @tp_error
|
364
|
+
lambda{tp('a=a').date('a')}.must_raise @tp_error
|
365
|
+
|
366
|
+
lambda{tp('a=').date!('a')}.must_raise @tp_error
|
367
|
+
tp('a=2017-10-11').date!('a').must_equal Date.new(2017, 10, 11)
|
368
|
+
|
369
|
+
tp('a[]=2017-10-11&a[]=2017-10-12').array(:date, 'a').must_equal [Date.new(2017, 10, 11), Date.new(2017, 10, 12)]
|
370
|
+
tp('a[]=2017-10-11&a[]=2017-10-12').array(:date, 'b').must_be_nil
|
371
|
+
|
372
|
+
tp('a[]=2017-10-11&a[]=2017-10-12').array!(:date, 'a').must_equal [Date.new(2017, 10, 11), Date.new(2017, 10, 12)]
|
373
|
+
lambda{tp('a[]=2017-10-11&a[]=a').array!(:date, 'a')}.must_raise @tp_error
|
374
|
+
lambda{tp('a[]=2017-10-11&a[]=2017-10-12').array!(:date, 'b')}.must_raise @tp_error
|
375
|
+
end
|
376
|
+
|
377
|
+
it "#Time should parse strings into Time instances" do
|
378
|
+
tp('a=').time('a').must_be_nil
|
379
|
+
tp('a=2017-10-11%2012:13:14').time('a').must_equal Time.local(2017, 10, 11, 12, 13, 14)
|
380
|
+
tp('a=17/10/11%2012:13:14').time('a').must_equal Time.local(2017, 10, 11, 12, 13, 14)
|
381
|
+
lambda{tp.time('b')}.must_raise @tp_error
|
382
|
+
lambda{tp('a=a').time('a')}.must_raise @tp_error
|
383
|
+
|
384
|
+
lambda{tp('a=').time!('a')}.must_raise @tp_error
|
385
|
+
tp('a=2017-10-11%2012:13:14').time!('a').must_equal Time.new(2017, 10, 11, 12, 13, 14)
|
386
|
+
|
387
|
+
tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array(:time, 'a').must_equal [Time.local(2017, 10, 11, 12, 13, 14), Time.local(2017, 10, 12, 12, 13, 14)]
|
388
|
+
tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array(:time, 'b').must_be_nil
|
389
|
+
|
390
|
+
tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array!(:time, 'a').must_equal [Time.local(2017, 10, 11, 12, 13, 14), Time.local(2017, 10, 12, 12, 13, 14)]
|
391
|
+
lambda{tp('a[]=2017-10-11%2012:13:14&a[]=a').array!(:time, 'a')}.must_raise @tp_error
|
392
|
+
lambda{tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array!(:time, 'b')}.must_raise @tp_error
|
393
|
+
end
|
394
|
+
|
395
|
+
it "#DateTime should parse strings into DateTime instances" do
|
396
|
+
tp('a=').datetime('a').must_be_nil
|
397
|
+
tp('a=2017-10-11%2012:13:14').datetime('a').must_equal DateTime.new(2017, 10, 11, 12, 13, 14)
|
398
|
+
tp('a=17/10/11%2012:13:14').datetime('a').must_equal DateTime.new(2017, 10, 11, 12, 13, 14)
|
399
|
+
lambda{tp.datetime('b')}.must_raise @tp_error
|
400
|
+
lambda{tp('a=a').datetime('a')}.must_raise @tp_error
|
401
|
+
|
402
|
+
lambda{tp('a=').datetime!('a')}.must_raise @tp_error
|
403
|
+
tp('a=2017-10-11%2012:13:14').datetime!('a').must_equal DateTime.new(2017, 10, 11, 12, 13, 14)
|
404
|
+
|
405
|
+
tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array(:datetime, 'a').must_equal [DateTime.new(2017, 10, 11, 12, 13, 14), DateTime.new(2017, 10, 12, 12, 13, 14)]
|
406
|
+
tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array(:datetime, 'b').must_be_nil
|
407
|
+
|
408
|
+
tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array!(:datetime, 'a').must_equal [DateTime.new(2017, 10, 11, 12, 13, 14), DateTime.new(2017, 10, 12, 12, 13, 14)]
|
409
|
+
lambda{tp('a[]=2017-10-11%2012:13:14&a[]=a').array!(:datetime, 'a')}.must_raise @tp_error
|
410
|
+
lambda{tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array!(:datetime, 'b')}.must_raise @tp_error
|
411
|
+
end
|
412
|
+
|
413
|
+
it "#array should handle defaults" do
|
414
|
+
tp = tp('b[]=1&c[]=')
|
415
|
+
tp.array(:int, 'b', [2]).must_equal [1]
|
416
|
+
tp.array(:int, 'c', [2]).must_equal [nil]
|
417
|
+
tp.array(:int, 'd', []).must_equal []
|
418
|
+
tp.array(:int, 'e', [1]).must_equal [1]
|
419
|
+
|
420
|
+
tp('b[]=1&c[]=').array(:int, %w'b c', [2]).must_equal [[1], [nil]]
|
421
|
+
tp('b[]=1&c[]=').array(:int, %w'b d', [2]).must_equal [[1], [2]]
|
422
|
+
end
|
423
|
+
|
424
|
+
it "#array! should handle defaults" do
|
425
|
+
tp = tp('b[]=1&c[]=')
|
426
|
+
tp.array!(:int, 'b', [2]).must_equal [1]
|
427
|
+
lambda{tp.array!(:int, 'c', [2])}.must_raise @tp_error
|
428
|
+
tp.array!(:int, 'd', []).must_equal []
|
429
|
+
tp.array!(:int, 'e', [1]).must_equal [1]
|
430
|
+
|
431
|
+
lambda{tp('b[]=1&c[]=').array!(:int, %w'b c', [2])}.must_raise @tp_error
|
432
|
+
tp('b[]=1&c[]=').array!(:int, %w'b d', [2]).must_equal [[1], [2]]
|
433
|
+
end
|
434
|
+
|
435
|
+
it "#array should handle key arrays" do
|
436
|
+
tp('b[]=1&c[]=2').array(:int, %w'b c').must_equal [[1], [2]]
|
437
|
+
tp('b[]=1&c[]=').array(:int, %w'b c').must_equal [[1], [nil]]
|
438
|
+
end
|
439
|
+
|
440
|
+
it "#array! should handle key arrays" do
|
441
|
+
tp('b[]=1&c[]=2').array!(:int, %w'b c').must_equal [[1], [2]]
|
442
|
+
lambda{tp('b[]=1&c[]=').array!(:int, %w'b c')}.must_raise @tp_error
|
443
|
+
end
|
444
|
+
|
445
|
+
it "#[] should access nested values" do
|
446
|
+
tp['c'].must_be_kind_of tp.class
|
447
|
+
tp['c'].int('d').must_equal 4
|
448
|
+
tp['c'].int('e').must_equal 5
|
449
|
+
tp['c'].int(%w'd e').must_equal [4, 5]
|
450
|
+
end
|
451
|
+
|
452
|
+
it "#[] should handle deeply nested structures" do
|
453
|
+
tp('a[b][c][d][e]=1')['a']['b']['c']['d'].int('e').must_equal 1
|
454
|
+
tp('a[][b][][e]=1')['a'][0]['b'][0].int('e').must_equal 1
|
455
|
+
end
|
456
|
+
|
457
|
+
it "#[] should raise error for non-Array/Hash parameters" do
|
458
|
+
lambda{tp['a']}.must_raise @tp_error
|
459
|
+
end
|
460
|
+
|
461
|
+
it "#[] should raise error for accessing hash with integer value (thinking it is an array)" do
|
462
|
+
lambda{tp[1]}.must_raise @tp_error
|
463
|
+
end
|
464
|
+
|
465
|
+
it "#[] should raise error for accessing array with non-integer value non-Array/Hash parameters" do
|
466
|
+
lambda{tp['b']['a']}.must_raise @tp_error
|
467
|
+
end
|
468
|
+
|
469
|
+
it "#convert! should return a hash of converted parameters" do
|
470
|
+
tp = tp()
|
471
|
+
tp.convert! do |ptp|
|
472
|
+
ptp.int!('a')
|
473
|
+
ptp.array!(:int, 'b')
|
474
|
+
ptp['c'].convert! do |stp|
|
475
|
+
stp.int!(%w'd e')
|
476
|
+
end
|
477
|
+
end.must_equal("a"=>1, "b"=>[2, 3], "c"=>{"d"=>4, "e"=>5})
|
478
|
+
end
|
479
|
+
|
480
|
+
it "#convert! hash should only include changes made inside block" do
|
481
|
+
tp = tp()
|
482
|
+
tp.convert! do |ptp|
|
483
|
+
ptp.int!('a')
|
484
|
+
ptp.array!(:int, 'b')
|
485
|
+
end.must_equal("a"=>1, "b"=>[2, 3])
|
486
|
+
|
487
|
+
tp.convert! do |ptp|
|
488
|
+
ptp['c'].convert! do |stp|
|
489
|
+
stp.int!(%w'd e')
|
490
|
+
end
|
491
|
+
end.must_equal("c"=>{"d"=>4, "e"=>5})
|
492
|
+
end
|
493
|
+
|
494
|
+
it "#convert! should handle deeply nested structures" do
|
495
|
+
tp = tp('a[b][c][d][e]=1')
|
496
|
+
tp.convert! do |tp0|
|
497
|
+
tp0['a'].convert! do |tp1|
|
498
|
+
tp1['b'].convert! do |tp2|
|
499
|
+
tp2['c'].convert! do |tp3|
|
500
|
+
tp3['d'].convert! do |tp4|
|
501
|
+
tp4.int('e')
|
502
|
+
end
|
503
|
+
end
|
504
|
+
end
|
505
|
+
end
|
506
|
+
end.must_equal('a'=>{'b'=>{'c'=>{'d'=>{'e'=>1}}}})
|
507
|
+
|
508
|
+
tp = tp('a[][b][][e]=1')
|
509
|
+
tp.convert! do |tp0|
|
510
|
+
tp0['a'].convert! do |tp1|
|
511
|
+
tp1[0].convert! do |tp2|
|
512
|
+
tp2['b'].convert! do |tp3|
|
513
|
+
tp3[0].convert! do |tp4|
|
514
|
+
tp4.int('e')
|
515
|
+
end
|
516
|
+
end
|
517
|
+
end
|
518
|
+
end
|
519
|
+
end.must_equal('a'=>[{'b'=>[{'e'=>1}]}])
|
520
|
+
end
|
521
|
+
|
522
|
+
it "#convert! should handle #[] without #convert! at each level" do
|
523
|
+
tp = tp('a[b][c][d][e]=1')
|
524
|
+
tp.convert! do |tp0|
|
525
|
+
tp0['a'].convert! do |tp1|
|
526
|
+
tp1['b']['c']['d'].convert! do |tp4|
|
527
|
+
tp4.int('e')
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end.must_equal('a'=>{'b'=>{'c'=>{'d'=>{'e'=>1}}}})
|
531
|
+
end
|
532
|
+
|
533
|
+
it "#convert! should handle #[] without #convert! below" do
|
534
|
+
tp = tp('a[b][c][d][e]=1')
|
535
|
+
tp.convert! do |tp0|
|
536
|
+
tp0['a']['b']['c']['d'].int('e')
|
537
|
+
end.must_equal('a'=>{'b'=>{'c'=>{'d'=>{'e'=>1}}}})
|
538
|
+
end
|
539
|
+
|
540
|
+
it "#convert! should handle multiple calls to #[] and #convert! below" do
|
541
|
+
tp = tp('a[b]=2&a[c]=3&a[d]=4&a[e]=5&a[f]=6')
|
542
|
+
tp.convert! do |tp0|
|
543
|
+
tp0['a'].int('b')
|
544
|
+
tp0['a'].convert! do |tp1|
|
545
|
+
tp1.int('c')
|
546
|
+
end
|
547
|
+
tp0['a'].int('d')
|
548
|
+
tp0['a'].convert! do |tp1|
|
549
|
+
tp1.int('e')
|
550
|
+
end
|
551
|
+
tp0['a'].int('f')
|
552
|
+
end.must_equal('a'=>{'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5, 'f'=>6})
|
553
|
+
end
|
554
|
+
|
555
|
+
it "#convert! should handle defaults" do
|
556
|
+
tp.convert! do |tp0|
|
557
|
+
tp0.int('d', 12)
|
558
|
+
end.must_equal('d'=>12)
|
559
|
+
|
560
|
+
tp.convert! do |tp0|
|
561
|
+
tp0.int(%w'a d', 12)
|
562
|
+
end.must_equal('a'=>1, 'd'=>12)
|
563
|
+
|
564
|
+
tp.convert! do |tp0|
|
565
|
+
tp0.array(:int, 'g', [])
|
566
|
+
end.must_equal('g'=>[nil])
|
567
|
+
|
568
|
+
tp.convert! do |tp0|
|
569
|
+
tp0.array(:int, 'j', [])
|
570
|
+
end.must_equal('j'=>[])
|
571
|
+
|
572
|
+
tp('a[]=1&g[]=').convert! do |tp0|
|
573
|
+
tp0.array(:int, %w'a d g', [2])
|
574
|
+
end.must_equal('a'=>[1], 'd'=>[2], 'g'=>[nil])
|
575
|
+
end
|
576
|
+
|
577
|
+
it "#convert_each! should convert each entry in an array" do
|
578
|
+
tp = tp('a[][b]=1&a[][c]=2&a[][b]=3&a[][c]=4')
|
579
|
+
tp['a'].convert_each! do |tp0|
|
580
|
+
tp0.int(%w'b c')
|
581
|
+
end.must_equal [{'b'=>1, 'c'=>2}, {'b'=>3, 'c'=>4}]
|
582
|
+
end
|
583
|
+
|
584
|
+
it "#convert_each! with :keys option should convert each named entry in a hash" do
|
585
|
+
tp = tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4')
|
586
|
+
tp['a'].convert_each!(:keys=>%w'0 1') do |tp0|
|
587
|
+
tp0.int(%w'b c')
|
588
|
+
end.must_equal [{'b'=>1, 'c'=>2}, {'b'=>3, 'c'=>4}]
|
589
|
+
end
|
590
|
+
|
591
|
+
it "#convert_each! with :keys option should store entries when called inside convert" do
|
592
|
+
tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4').convert! do |tp|
|
593
|
+
tp['a'].convert_each!(:keys=>%w'0 1') do |tp0|
|
594
|
+
tp0.int(%w'b c')
|
595
|
+
end
|
596
|
+
end.must_equal("a"=>{"0"=>{'b'=>1, 'c'=>2}, "1"=>{'b'=>3, 'c'=>4}})
|
597
|
+
end
|
598
|
+
|
599
|
+
it "#convert_each! should raise if obj is not an array" do
|
600
|
+
lambda{tp.convert_each!{}}.must_raise @tp_error
|
601
|
+
end
|
602
|
+
|
603
|
+
it "#convert_each! should raise if obj is a array of non-hashes" do
|
604
|
+
lambda{tp['b'].convert_each!{}}.must_raise @tp_error
|
605
|
+
end
|
606
|
+
|
607
|
+
it "#convert! with :symbolize option should return a hash of converted parameters" do
|
608
|
+
tp = tp()
|
609
|
+
tp.convert!(:symbolize=>true) do |ptp|
|
610
|
+
ptp.int!('a')
|
611
|
+
ptp.array!(:int, 'b')
|
612
|
+
ptp['c'].convert! do |stp|
|
613
|
+
stp.int!(%w'd e')
|
614
|
+
end
|
615
|
+
end.must_equal(:a=>1, :b=>[2, 3], :c=>{:d=>4, :e=>5})
|
616
|
+
end
|
617
|
+
|
618
|
+
it "#convert! with :symbolize option hash should only include changes made inside block" do
|
619
|
+
tp = tp()
|
620
|
+
tp.convert!(:symbolize=>true) do |ptp|
|
621
|
+
ptp.int!('a')
|
622
|
+
ptp.array!(:int, 'b')
|
623
|
+
end.must_equal(:a=>1, :b=>[2, 3])
|
624
|
+
|
625
|
+
tp.convert!(:symbolize=>true) do |ptp|
|
626
|
+
ptp['c'].convert! do |stp|
|
627
|
+
stp.int!(%w'd e')
|
628
|
+
end
|
629
|
+
end.must_equal(:c=>{:d=>4, :e=>5})
|
630
|
+
end
|
631
|
+
|
632
|
+
it "#convert! with :symbolize option should handle deeply nested structures" do
|
633
|
+
tp = tp('a[b][c][d][e]=1')
|
634
|
+
tp.convert!(:symbolize=>true) do |tp0|
|
635
|
+
tp0['a'].convert! do |tp1|
|
636
|
+
tp1['b'].convert! do |tp2|
|
637
|
+
tp2['c'].convert! do |tp3|
|
638
|
+
tp3['d'].convert! do |tp4|
|
639
|
+
tp4.int('e')
|
640
|
+
end
|
641
|
+
end
|
642
|
+
end
|
643
|
+
end
|
644
|
+
end.must_equal(:a=>{:b=>{:c=>{:d=>{:e=>1}}}})
|
645
|
+
|
646
|
+
tp = tp('a[][b][][e]=1')
|
647
|
+
tp.convert!(:symbolize=>true) do |tp0|
|
648
|
+
tp0['a'].convert! do |tp1|
|
649
|
+
tp1[0].convert! do |tp2|
|
650
|
+
tp2['b'].convert! do |tp3|
|
651
|
+
tp3[0].convert! do |tp4|
|
652
|
+
tp4.int('e')
|
653
|
+
end
|
654
|
+
end
|
655
|
+
end
|
656
|
+
end
|
657
|
+
end.must_equal(:a=>[{:b=>[{:e=>1}]}])
|
658
|
+
end
|
659
|
+
|
660
|
+
it "#convert! with :symbolize option should handle #[] without #convert! at each level" do
|
661
|
+
tp = tp('a[b][c][d][e]=1')
|
662
|
+
tp.convert!(:symbolize=>true) do |tp0|
|
663
|
+
tp0['a'].convert! do |tp1|
|
664
|
+
tp1['b']['c']['d'].convert! do |tp4|
|
665
|
+
tp4.int('e')
|
666
|
+
end
|
667
|
+
end
|
668
|
+
end.must_equal(:a=>{:b=>{:c=>{:d=>{:e=>1}}}})
|
669
|
+
end
|
670
|
+
|
671
|
+
it "#convert! with :symbolize option should handle #[] without #convert! below" do
|
672
|
+
tp = tp('a[b][c][d][e]=1')
|
673
|
+
tp.convert!(:symbolize=>true) do |tp0|
|
674
|
+
tp0['a']['b']['c']['d'].int('e')
|
675
|
+
end.must_equal(:a=>{:b=>{:c=>{:d=>{:e=>1}}}})
|
676
|
+
end
|
677
|
+
|
678
|
+
it "#convert! with :symbolize option should handle multiple calls to #[] and #convert! below" do
|
679
|
+
tp = tp('a[b]=2&a[c]=3&a[d]=4&a[e]=5&a[f]=6')
|
680
|
+
tp.convert!(:symbolize=>true) do |tp0|
|
681
|
+
tp0['a'].int('b')
|
682
|
+
tp0['a'].convert! do |tp1|
|
683
|
+
tp1.int('c')
|
684
|
+
end
|
685
|
+
tp0['a'].int('d')
|
686
|
+
tp0['a'].convert! do |tp1|
|
687
|
+
tp1.int('e')
|
688
|
+
end
|
689
|
+
tp0['a'].int('f')
|
690
|
+
end.must_equal(:a=>{:b=>2, :c=>3, :d=>4, :e=>5, :f=>6})
|
691
|
+
end
|
692
|
+
|
693
|
+
it "#convert! with :symbolize option should handle defaults" do
|
694
|
+
tp.convert!(:symbolize=>true) do |tp0|
|
695
|
+
tp0.int('d', 12)
|
696
|
+
end.must_equal(:d=>12)
|
697
|
+
|
698
|
+
tp.convert!(:symbolize=>true) do |tp0|
|
699
|
+
tp0.int(%w'a d', 12)
|
700
|
+
end.must_equal(:a=>1, :d=>12)
|
701
|
+
|
702
|
+
tp.convert!(:symbolize=>true) do |tp0|
|
703
|
+
tp0.array(:int, 'g', [])
|
704
|
+
end.must_equal(:g=>[nil])
|
705
|
+
|
706
|
+
tp.convert!(:symbolize=>true) do |tp0|
|
707
|
+
tp0.array(:int, 'j', [])
|
708
|
+
end.must_equal(:j=>[])
|
709
|
+
|
710
|
+
tp('a[]=1&g[]=').convert!(:symbolize=>true) do |tp0|
|
711
|
+
tp0.array(:int, %w'a d g', [2])
|
712
|
+
end.must_equal(:a=>[1], :d=>[2], :g=>[nil])
|
713
|
+
end
|
714
|
+
|
715
|
+
it "#convert_each! with :symbolize option should convert each entry in an array" do
|
716
|
+
tp = tp('a[][b]=1&a[][c]=2&a[][b]=3&a[][c]=4')
|
717
|
+
tp['a'].convert_each!(:symbolize=>true) do |tp0|
|
718
|
+
tp0.int(%w'b c')
|
719
|
+
end.must_equal [{:b=>1, :c=>2}, {:b=>3, :c=>4}]
|
720
|
+
end
|
721
|
+
|
722
|
+
it "#convert_each! with :symbolize and :keys options should convert each named entry in a hash" do
|
723
|
+
tp = tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4')
|
724
|
+
tp['a'].convert_each!(:keys=>%w'0 1', :symbolize=>true) do |tp0|
|
725
|
+
tp0.int(%w'b c')
|
726
|
+
end.must_equal [{:b=>1, :c=>2}, {:b=>3, :c=>4}]
|
727
|
+
end
|
728
|
+
|
729
|
+
it "#convert_each! with :symbolize and :keys options should store entries when called inside convert" do
|
730
|
+
tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4').convert!(:symbolize=>true) do |tp|
|
731
|
+
tp['a'].convert_each!(:keys=>%w'0 1') do |tp0|
|
732
|
+
tp0.int(%w'b c')
|
733
|
+
end
|
734
|
+
end.must_equal(:a=>{:'0'=>{:b=>1, :c=>2}, :'1'=>{:b=>3, :c=>4}})
|
735
|
+
end
|
736
|
+
|
737
|
+
it "#convert! with :symbolize options specified at different levels should work" do
|
738
|
+
tp = tp('a[b][c][d][e]=1')
|
739
|
+
tp.convert!(:symbolize=>true) do |tp0|
|
740
|
+
tp0['a'].convert!(:symbolize=>false) do |tp1|
|
741
|
+
tp1['b'].convert!(:symbolize=>true) do |tp2|
|
742
|
+
tp2['c'].convert!(:symbolize=>false) do |tp3|
|
743
|
+
tp3['d'].convert!(:symbolize=>true) do |tp4|
|
744
|
+
tp4.int('e')
|
745
|
+
end
|
746
|
+
end
|
747
|
+
end
|
748
|
+
end
|
749
|
+
end.must_equal(:a=>{'b'=>{:c=>{'d'=>{:e=>1}}}})
|
750
|
+
|
751
|
+
tp = tp('a[][b][][e]=1')
|
752
|
+
tp.convert!(:symbolize=>true) do |tp0|
|
753
|
+
tp0['a'].convert! do |tp1|
|
754
|
+
tp1[0].convert!(:symbolize=>false) do |tp2|
|
755
|
+
tp2['b'].convert! do |tp3|
|
756
|
+
tp3[0].convert!(:symbolize=>true) do |tp4|
|
757
|
+
tp4.int('e')
|
758
|
+
end
|
759
|
+
end
|
760
|
+
end
|
761
|
+
end
|
762
|
+
end.must_equal(:a=>[{'b'=>[{:e=>1}]}])
|
763
|
+
end
|
764
|
+
|
765
|
+
it "#dig should return nested values or nil if there is no value" do
|
766
|
+
tp = tp('a[b][c][d][e]=1&b=2')
|
767
|
+
tp.dig(:int, 'a', 'b', 'c', 'd', 'e').must_equal 1
|
768
|
+
tp.dig(:int, 'b').must_equal 2
|
769
|
+
tp.dig(:int, 'a', 0, 'c', 'd', 'e').must_be_nil
|
770
|
+
tp.dig(:int, 'a', 'd', 'c', 'd', 'e').must_be_nil
|
771
|
+
tp.dig(:int, 'a', 'b', 'c', 'd', 'f').must_be_nil
|
772
|
+
tp.dig(:int, 'c').must_be_nil
|
773
|
+
tp.dig(:int, 'c', 'd').must_be_nil
|
774
|
+
|
775
|
+
tp = tp('a[][c][][e]=1')
|
776
|
+
tp.dig(:int, 'a', 0, 'c', 0, 'e').must_equal 1
|
777
|
+
tp.dig(:int, 'a', 1, 'c', 0, 'e').must_be_nil
|
778
|
+
tp.dig(:int, 'a', 'b', 'c', 0, 'e').must_be_nil
|
779
|
+
tp.dig(:int, 'a', 0, 'c', 0, 'f').must_be_nil
|
780
|
+
end
|
781
|
+
|
782
|
+
it "#dig should raise when accessing past the end of the expected structure" do
|
783
|
+
tp = tp('a[b][c][d][e]=1&b=2')
|
784
|
+
lambda{tp.dig(:int, 'a', 'b', 'c', 'd', 'e', 'f')}.must_raise @tp_error
|
785
|
+
lambda{tp.dig(:int, 'b', 'c')}.must_raise @tp_error
|
786
|
+
|
787
|
+
tp = tp('a[][c][][e]=1')
|
788
|
+
lambda{tp.dig(:int, 'a', 0, 'c', 0, 'e', 'f')}.must_raise @tp_error
|
789
|
+
end
|
790
|
+
|
791
|
+
it "#dig and #dig! should handle array keys" do
|
792
|
+
tp('a[b][c][d][e]=1&a[b][c][d][f]=2').dig(:int, 'a', 'b', 'c', 'd', %w'e f').must_equal [1, 2]
|
793
|
+
tp('a[b][c][d][e]=1&a[b][c][d][f]=').dig(:int, 'a', 'b', 'c', 'd', %w'e f').must_equal [1, nil]
|
794
|
+
|
795
|
+
tp('a[b][c][d][e]=1&a[b][c][d][f]=2').dig!(:int, 'a', 'b', 'c', 'd', %w'e f').must_equal [1, 2]
|
796
|
+
lambda{tp('a[b][c][d][e]=1&a[b][c][d][f]=').dig!(:int, 'a', 'b', 'c', 'd', %w'e f')}.must_raise @tp_error
|
797
|
+
end
|
798
|
+
|
799
|
+
it "#dig and #dig! should be able to handle arrays using an array for the type" do
|
800
|
+
tp('a[b][c][d][]=1&a[b][c][d][]=2').dig(:array, :int, 'a', 'b', 'c', 'd').must_equal [1, 2]
|
801
|
+
tp('a[b][c][d][]=1&a[b][c][d][]=').dig(:array, :int, 'a', 'b', 'c', 'd').must_equal [1, nil]
|
802
|
+
|
803
|
+
tp('a[b][c][d][]=1&a[b][c][d][]=2').dig!(:array!, :int, 'a', 'b', 'c', 'd').must_equal [1, 2]
|
804
|
+
lambda{tp('a[b][c][d][]=1&a[b][c][d][]=').dig!(:array!, :int, 'a', 'b', 'c', 'd')}.must_raise @tp_error
|
805
|
+
end
|
806
|
+
|
807
|
+
it "#dig should raise for unsupported types" do
|
808
|
+
lambda{tp.dig(:foo, 'a')}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
|
809
|
+
end
|
810
|
+
|
811
|
+
it "#dig should raise for array without subtype" do
|
812
|
+
lambda{tp.dig(:array, 'foo', 'a')}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
|
813
|
+
end
|
814
|
+
|
815
|
+
|
816
|
+
it "#dig should raise for unsupported nest values" do
|
817
|
+
lambda{tp.dig(:int, :foo, 'a')}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
|
818
|
+
lambda{tp.dig(:array, :int, :foo, 'a')}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
|
819
|
+
end
|
820
|
+
|
821
|
+
it "#dig! should return nested values or raise Error if thers is no value" do
|
822
|
+
tp = tp('a[b][c][d][e]=1&b=2')
|
823
|
+
tp.dig!(:int, 'a', 'b', 'c', 'd', 'e').must_equal 1
|
824
|
+
tp.dig!(:int, 'b').must_equal 2
|
825
|
+
lambda{tp.dig!(:int, 'a', 'd', 'c', 'd', 'e')}.must_raise @tp_error
|
826
|
+
lambda{tp.dig!(:int, 'a', 'b', 'c', 'd', 'f')}.must_raise @tp_error
|
827
|
+
lambda{tp.dig!(:int, 'a', 0, 'c', 'd', 'f')}.must_raise @tp_error
|
828
|
+
lambda{tp.dig!(:int, 'c')}.must_raise @tp_error
|
829
|
+
lambda{tp.dig!(:int, 'b', 'c')}.must_raise @tp_error
|
830
|
+
lambda{tp.dig!(:int, 'c', 'd')}.must_raise @tp_error
|
831
|
+
error{tp.dig!(:int, 'a', 'd', 'c', 'd', 'e')}.keys.must_equal %w'a d'
|
832
|
+
error{tp.dig!(:int, 'a', 'b', 'c', 'e', 'e')}.keys.must_equal %w'a b c e'
|
833
|
+
|
834
|
+
tp = tp('a[][c][][e]=1')
|
835
|
+
tp.dig!(:int, 'a', 0, 'c', 0, 'e').must_equal 1
|
836
|
+
lambda{tp.dig!(:int, 'a', 1, 'c', 0, 'e')}.must_raise @tp_error
|
837
|
+
lambda{tp.dig!(:int, 'a', 'b', 'c', 0, 'e')}.must_raise @tp_error
|
838
|
+
lambda{tp.dig!(:int, 'a', 0, 'c', 0, 'f')}.must_raise @tp_error
|
839
|
+
end
|
840
|
+
|
841
|
+
it "#convert! should work with dig" do
|
842
|
+
tp('a[b][c][d][e]=1').convert! do |tp|
|
843
|
+
tp.dig(:int, 'a', 'b', 'c', 'd', 'e')
|
844
|
+
end.must_equal('a'=>{'b'=>{'c'=>{'d'=>{'e'=>1}}}})
|
845
|
+
end
|
846
|
+
|
847
|
+
it "#convert! with :symbolize option should work with dig" do
|
848
|
+
tp('a[b][c][d][e]=1').convert!(:symbolize=>true) do |tp|
|
849
|
+
tp.dig(:int, 'a', 'b', 'c', 'd', 'e')
|
850
|
+
end.must_equal(:a=>{:b=>{:c=>{:d=>{:e=>1}}}})
|
851
|
+
end
|
852
|
+
|
853
|
+
it "#fetch should be the same as #[] if the key is present" do
|
854
|
+
tp.fetch('c').int('d').must_equal 4
|
855
|
+
end
|
856
|
+
|
857
|
+
it "#fetch should return nil if the key is not present and no block is given" do
|
858
|
+
tp.fetch('d').must_be_nil
|
859
|
+
end
|
860
|
+
|
861
|
+
it "#fetch should call the block if the key is not present and a block is given" do
|
862
|
+
tp.fetch('d'){1}.must_equal 1
|
863
|
+
end
|
864
|
+
|
865
|
+
it "Error#keys should be a path to the error" do
|
866
|
+
error{tp.int!('b')}.keys.must_equal ['b']
|
867
|
+
error{tp.int!(%w'b f')}.keys.must_equal ['b']
|
868
|
+
error{tp['c'].int!('f')}.keys.must_equal ['c', 'f']
|
869
|
+
error{tp('a[b][c][d][e]=1')['a']['b']['c']['d'].date('e')}.keys.must_equal %w'a b c d e'
|
870
|
+
end
|
871
|
+
|
872
|
+
it "Error#param_name should be the name of the parameter" do
|
873
|
+
error{tp.int!('b')}.param_name.must_equal 'b'
|
874
|
+
error{tp.int!(%w'b f')}.param_name.must_equal 'b'
|
875
|
+
error{tp['c'].int!('f')}.param_name.must_equal 'c[f]'
|
876
|
+
error{tp('a[b][c][d][e]=1')['a']['b']['c']['d'].date('e')}.param_name.must_equal 'a[b][c][d][e]'
|
877
|
+
error{tp('a[][c][][e]=1')['a'][0]['c'][0].date('e')}.param_name.must_equal 'a[][c][][e]'
|
878
|
+
error{tp('a[][c][][e]=1').dig(:date, 'a', 0, 'c', 0, 'e')}.param_name.must_equal 'a[][c][][e]'
|
879
|
+
end
|
880
|
+
|
881
|
+
it "Error#param_names and #reason should be correct for errors" do
|
882
|
+
e = error{tp.int!('b')}
|
883
|
+
e.param_names.must_equal ['b']
|
884
|
+
e.reason.must_equal :int
|
885
|
+
|
886
|
+
e = error{tp.int!(%w'b f')}
|
887
|
+
e.param_names.must_equal ['b']
|
888
|
+
e.reason.must_equal :int
|
889
|
+
|
890
|
+
e = error{tp['c'].int!('f')}
|
891
|
+
e.param_names.must_equal ['c[f]']
|
892
|
+
e.reason.must_equal :missing
|
893
|
+
|
894
|
+
e = error{tp('a[b][c][d][e]=1')['a']['b']['c']['d'].date('e')}
|
895
|
+
e.param_names.must_equal ['a[b][c][d][e]']
|
896
|
+
e.reason.must_equal :date
|
897
|
+
|
898
|
+
e = error{tp('a[][c][][e]=1')['a'][0]['c'][0].date('e')}
|
899
|
+
e.param_names.must_equal ['a[][c][][e]']
|
900
|
+
e.reason.must_equal :date
|
901
|
+
|
902
|
+
e = error{tp('a[][c][][e]=1').dig(:date, 'a', 0, 'c', 0, 'e')}
|
903
|
+
e.param_names.must_equal ['a[][c][][e]']
|
904
|
+
e.reason.must_equal :date
|
905
|
+
|
906
|
+
e = error{tp('a[][c][][e]=1').dig!(:date, 'a', 1, 'c', 0, 'e')}
|
907
|
+
e.param_names.must_equal ['a[]']
|
908
|
+
e.reason.must_equal :missing
|
909
|
+
|
910
|
+
e = error{tp('a[][c][][e]=1').dig!(:date, 'a', 'b', 'c', 0, 'e')}
|
911
|
+
e.param_names.must_equal ['a[b]']
|
912
|
+
e.reason.must_equal :invalid_type
|
913
|
+
end
|
914
|
+
|
915
|
+
it "Error#param_names and #all_errors should handle array submission" do
|
916
|
+
tp = tp('a[][b]=0')
|
917
|
+
e = error do
|
918
|
+
tp.convert!('a') do |tp0|
|
919
|
+
tp0.int(%w'a b c')
|
920
|
+
tp0.array(:int, %w'a b c')
|
921
|
+
end
|
922
|
+
end
|
923
|
+
e.param_names.must_equal %w'a'
|
924
|
+
e.all_errors.map(&:reason).must_equal [:invalid_type]
|
925
|
+
end
|
926
|
+
|
927
|
+
it "Error#param_names and #all_errors should include all errors raised in convert! blocks" do
|
928
|
+
tp = tp('a[][b][][e]=0')
|
929
|
+
e = error do
|
930
|
+
tp.convert! do |tp0|
|
931
|
+
tp0['a'].convert! do |tp1|
|
932
|
+
tp1[0].convert! do |tp2|
|
933
|
+
tp2['b'].convert! do |tp3|
|
934
|
+
tp3[0].convert! do |tp4|
|
935
|
+
tp4.pos_int!('e')
|
936
|
+
end
|
937
|
+
end
|
938
|
+
end
|
939
|
+
end
|
940
|
+
tp0.dig!(:pos_int, 'a', 0, 'b', 0, %w'f g')
|
941
|
+
tp0.dig!(:pos_int, 'a', 0, 'b')
|
942
|
+
tp0.int!('c')
|
943
|
+
tp0.array!(:int, %w'd e')
|
944
|
+
tp0['b']
|
945
|
+
end
|
946
|
+
end
|
947
|
+
e.param_names.must_equal %w'a[][b][][e] a[][b][][f] a[][b][][g] a[][b] c d e b'
|
948
|
+
e.all_errors.map(&:reason).must_equal [:missing, :missing, :missing, :pos_int, :missing, :missing, :missing, :missing]
|
949
|
+
end
|
950
|
+
|
951
|
+
it "Error#param_names and #all_errors should handle #[] failures by skipping the rest of the block" do
|
952
|
+
tp = tp('a[][b][][e]=0')
|
953
|
+
e = error do
|
954
|
+
tp.convert! do |tp0|
|
955
|
+
tp0['b']
|
956
|
+
tp0.int!('c')
|
957
|
+
end
|
958
|
+
end
|
959
|
+
e.param_names.must_equal %w'b'
|
960
|
+
e.all_errors.map(&:reason).must_equal [:missing]
|
961
|
+
|
962
|
+
e = error do
|
963
|
+
tp.convert! do |tp0|
|
964
|
+
tp0['a'][0].convert! do |tp1|
|
965
|
+
tp1['c']
|
966
|
+
tp1.int!('d')
|
967
|
+
end
|
968
|
+
tp0.int!('c')
|
969
|
+
end
|
970
|
+
end
|
971
|
+
e.param_names.must_equal %w'a[][c] c'
|
972
|
+
e.all_errors.map(&:reason).must_equal [:missing, :missing]
|
973
|
+
end
|
974
|
+
|
975
|
+
it "Error#param_names and #all_errorsshould handle array! with array of keys where one of the keys is not present" do
|
976
|
+
e = error do
|
977
|
+
tp('e[]=0').convert! do |tp0|
|
978
|
+
tp0.array!(:pos_int, %w'd e')
|
979
|
+
end
|
980
|
+
end
|
981
|
+
e.param_names.must_equal %w'd e'
|
982
|
+
e.all_errors.map(&:reason).must_equal [:missing, :invalid_type]
|
983
|
+
end
|
984
|
+
|
985
|
+
it "Error#param_names and #all_errors should handle keys given to convert" do
|
986
|
+
tp = tp('e[][b][][e]=0')
|
987
|
+
e = error do
|
988
|
+
tp.convert! do |tp0|
|
989
|
+
tp0.convert!(['a', 0, 'b', 0]) do |tp1|
|
990
|
+
tp1.pos_int!('e')
|
991
|
+
end
|
992
|
+
tp0.convert!('f') do |tp1|
|
993
|
+
tp1.dig!(:pos_int, 0, 'b', 0, %w'f g')
|
994
|
+
end
|
995
|
+
tp0.dig!(:pos_int, 'e', 0, 'b')
|
996
|
+
tp0.int!('c')
|
997
|
+
tp0.array!(:int, 'd')
|
998
|
+
end
|
999
|
+
end
|
1000
|
+
e.param_names.must_equal %w'a f e[][b] c d'
|
1001
|
+
e.all_errors.map(&:reason).must_equal [:missing, :missing, :pos_int, :missing, :missing]
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
it "Error#param_names and #all_errors should include all errors raised in convert_each! blocks" do
|
1005
|
+
e = error do
|
1006
|
+
tp('a[][b]=0&a[][b]=1')['a'].convert_each! do |tp0|
|
1007
|
+
tp0.dig!(:pos_int, 'b', 0, 'e')
|
1008
|
+
tp0.dig!(:int, 'b', 0, %w'f g')
|
1009
|
+
tp0.int!(%w'd e')
|
1010
|
+
tp0.pos_int!('b')
|
1011
|
+
tp0['c']
|
1012
|
+
end
|
1013
|
+
end
|
1014
|
+
e.param_names.must_equal %w'a[][b] a[][b] a[][d] a[][e] a[][b] a[][c] a[][b] a[][b] a[][d] a[][e] a[][c]'
|
1015
|
+
e.all_errors.map(&:reason).must_equal [:invalid_type, :invalid_type, :missing, :missing, :missing, :missing, :invalid_type, :invalid_type, :missing, :missing, :missing]
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
it "Error#param_names and #all_errors should include all errors for invalid keys used in convert_each!" do
|
1019
|
+
tp = tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4')
|
1020
|
+
e = error do
|
1021
|
+
tp['a'].convert_each!(:keys=>%w'0 2 3') do |tp0|
|
1022
|
+
tp0.int(%w'b c')
|
1023
|
+
end
|
1024
|
+
end
|
1025
|
+
e.param_names.must_equal %w'a[2] a[3]'
|
1026
|
+
e.all_errors.map(&:reason).must_equal [:missing, :missing]
|
1027
|
+
end
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
describe "typecast_params plugin with customized params" do
|
1031
|
+
def tp(arg='a=1&b[]=2&b[]=3&c[d]=4&c[e]=5&f=&g[]=&h[i]=')
|
1032
|
+
@tp.call(arg)
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
before do
|
1036
|
+
res = nil
|
1037
|
+
app(:bare) do
|
1038
|
+
plugin :typecast_params do
|
1039
|
+
handle_type(:opp_int) do |v|
|
1040
|
+
-v.to_i
|
1041
|
+
end
|
1042
|
+
end
|
1043
|
+
plugin :typecast_params do
|
1044
|
+
handle_type(:double) do |v|
|
1045
|
+
v*2
|
1046
|
+
end
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
route do |r|
|
1050
|
+
res = typecast_params
|
1051
|
+
nil
|
1052
|
+
end
|
1053
|
+
end
|
1054
|
+
|
1055
|
+
@tp = lambda do |params|
|
1056
|
+
req('QUERY_STRING'=>params, 'rack.input'=>StringIO.new)
|
1057
|
+
res
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
@tp_error = Roda::RodaPlugins::TypecastParams::Error
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
it "should not allow typecast params changes after freezing the app" do
|
1064
|
+
app.freeze
|
1065
|
+
lambda{app::TypecastParams.handle_type(:foo){|v| v}}.must_raise RuntimeError
|
1066
|
+
end
|
1067
|
+
|
1068
|
+
it "should pass through non-ArgumentError exceptions raised by conversion blocks" do
|
1069
|
+
app::TypecastParams.handle_type(:foo){|v| raise}
|
1070
|
+
lambda{tp.foo('a')}.must_raise RuntimeError
|
1071
|
+
end
|
1072
|
+
|
1073
|
+
it "should respect custom typecasting methods" do
|
1074
|
+
tp.opp_int('a').must_equal -1
|
1075
|
+
tp.opp_int!('a').must_equal -1
|
1076
|
+
tp.opp_int('d').must_be_nil
|
1077
|
+
lambda{tp.opp_int!('d')}.must_raise @tp_error
|
1078
|
+
|
1079
|
+
tp.array(:opp_int, 'b').must_equal [-2, -3]
|
1080
|
+
tp.array!(:opp_int, 'b').must_equal [-2, -3]
|
1081
|
+
|
1082
|
+
tp.double('a').must_equal '11'
|
1083
|
+
tp.double!('a').must_equal '11'
|
1084
|
+
tp.double('d').must_be_nil
|
1085
|
+
lambda{tp.double!('d')}.must_raise @tp_error
|
1086
|
+
|
1087
|
+
tp.array(:double, 'b').must_equal ['22', '33']
|
1088
|
+
tp.array!(:double, 'b').must_equal ['22', '33']
|
1089
|
+
end
|
1090
|
+
|
1091
|
+
it "should respect custom typecasting methods when subclassing" do
|
1092
|
+
@app = Class.new(@app)
|
1093
|
+
@app.plugin :typecast_params do
|
1094
|
+
handle_type :triple do |v|
|
1095
|
+
v * 3
|
1096
|
+
end
|
1097
|
+
end
|
1098
|
+
|
1099
|
+
tp.opp_int('a').must_equal -1
|
1100
|
+
tp.opp_int!('a').must_equal -1
|
1101
|
+
tp.opp_int('d').must_be_nil
|
1102
|
+
lambda{tp.opp_int!('d')}.must_raise @tp_error
|
1103
|
+
|
1104
|
+
tp.array(:opp_int, 'b').must_equal [-2, -3]
|
1105
|
+
tp.array!(:opp_int, 'b').must_equal [-2, -3]
|
1106
|
+
|
1107
|
+
tp.double('a').must_equal '11'
|
1108
|
+
tp.double!('a').must_equal '11'
|
1109
|
+
tp.double('d').must_be_nil
|
1110
|
+
lambda{tp.double!('d')}.must_raise @tp_error
|
1111
|
+
|
1112
|
+
tp.array(:double, 'b').must_equal ['22', '33']
|
1113
|
+
tp.array!(:double, 'b').must_equal ['22', '33']
|
1114
|
+
|
1115
|
+
tp.triple('a').must_equal '111'
|
1116
|
+
tp.triple!('a').must_equal '111'
|
1117
|
+
tp.triple('d').must_be_nil
|
1118
|
+
lambda{tp.triple!('d')}.must_raise @tp_error
|
1119
|
+
|
1120
|
+
tp.array(:triple, 'b').must_equal ['222', '333']
|
1121
|
+
tp.array!(:triple, 'b').must_equal ['222', '333']
|
1122
|
+
end
|
1123
|
+
end
|
1124
|
+
|
1125
|
+
describe "typecast_params plugin with files" do
|
1126
|
+
def tp
|
1127
|
+
@tp.call
|
1128
|
+
end
|
1129
|
+
|
1130
|
+
before do
|
1131
|
+
tempfile = @tempfile = Tempfile.new(['roda_typecast_params_spec', '.txt'])
|
1132
|
+
tempfile.write('tp_spec')
|
1133
|
+
tempfile.rewind
|
1134
|
+
res = nil
|
1135
|
+
app(:typecast_params) do |r|
|
1136
|
+
res = typecast_params
|
1137
|
+
nil
|
1138
|
+
end
|
1139
|
+
app::RodaRequest.send(:define_method, :params) do
|
1140
|
+
{'testfile'=>{:tempfile=>tempfile}, 'testfile2'=>{:tempfile=>tempfile},
|
1141
|
+
'testfile_array'=>[{:tempfile=>tempfile}, {:tempfile=>tempfile}],
|
1142
|
+
'a'=>{'b'=>'c', 'tempfile'=>'f'},
|
1143
|
+
'c'=>['']}
|
1144
|
+
end
|
1145
|
+
|
1146
|
+
@tp = lambda do
|
1147
|
+
req
|
1148
|
+
res
|
1149
|
+
end
|
1150
|
+
|
1151
|
+
@tp_error = Roda::RodaPlugins::TypecastParams::Error
|
1152
|
+
end
|
1153
|
+
|
1154
|
+
it "#file should require an uploaded file" do
|
1155
|
+
tp.file('testfile').must_equal(:tempfile=>@tempfile)
|
1156
|
+
tp.file(%w'testfile testfile2').must_equal [{:tempfile=>@tempfile}, {:tempfile=>@tempfile}]
|
1157
|
+
|
1158
|
+
lambda{tp.file('a')}.must_raise @tp_error
|
1159
|
+
tp.file('b').must_be_nil
|
1160
|
+
lambda{tp.file('c')}.must_raise @tp_error
|
1161
|
+
|
1162
|
+
tp.file!('testfile').must_equal(:tempfile=>@tempfile)
|
1163
|
+
tp.file!(%w'testfile testfile2').must_equal [{:tempfile=>@tempfile}, {:tempfile=>@tempfile}]
|
1164
|
+
lambda{tp.file!('a')}.must_raise @tp_error
|
1165
|
+
lambda{tp.file!('b')}.must_raise @tp_error
|
1166
|
+
lambda{tp.file!('c')}.must_raise @tp_error
|
1167
|
+
|
1168
|
+
tp.array(:file, 'testfile_array').must_equal [{:tempfile=>@tempfile}, {:tempfile=>@tempfile}]
|
1169
|
+
lambda{tp.array(:file, 'testfile')}.must_raise @tp_error
|
1170
|
+
lambda{tp.array(:file, 'a')}.must_raise @tp_error
|
1171
|
+
tp.array(:file, 'b').must_be_nil
|
1172
|
+
lambda{tp.array(:file, 'c')}.must_raise @tp_error
|
1173
|
+
|
1174
|
+
tp.array!(:file, 'testfile_array').must_equal [{:tempfile=>@tempfile}, {:tempfile=>@tempfile}]
|
1175
|
+
lambda{tp.array!(:file, 'testfile')}.must_raise @tp_error
|
1176
|
+
lambda{tp.array!(:file, 'a')}.must_raise @tp_error
|
1177
|
+
lambda{tp.array!(:file, 'b')}.must_raise @tp_error
|
1178
|
+
lambda{tp.array!(:file, 'c')}.must_raise @tp_error
|
1179
|
+
end
|
1180
|
+
end
|
1181
|
+
|
1182
|
+
describe "typecast_params plugin with strip: :all option" do
|
1183
|
+
def tp(arg='a=+1+')
|
1184
|
+
@tp.call(arg)
|
1185
|
+
end
|
1186
|
+
|
1187
|
+
|
1188
|
+
before do
|
1189
|
+
res = nil
|
1190
|
+
app(:bare) do
|
1191
|
+
plugin :typecast_params, strip: :all
|
1192
|
+
route do |r|
|
1193
|
+
res = typecast_params
|
1194
|
+
nil
|
1195
|
+
end
|
1196
|
+
end
|
1197
|
+
|
1198
|
+
@tp = lambda do |params|
|
1199
|
+
req('QUERY_STRING'=>params, 'rack.input'=>StringIO.new)
|
1200
|
+
res
|
1201
|
+
end
|
1202
|
+
|
1203
|
+
@tp_error = Roda::RodaPlugins::TypecastParams::Error
|
1204
|
+
end
|
1205
|
+
|
1206
|
+
it "#file should require an uploaded file" do
|
1207
|
+
tp.str('a').must_equal '1'
|
1208
|
+
tp.nonempty_str('a').must_equal '1'
|
1209
|
+
tp.int('a').must_equal 1
|
1210
|
+
tp.pos_int('a').must_equal 1
|
1211
|
+
tp.Integer('a').must_equal 1
|
1212
|
+
tp.float('a').must_equal 1.0
|
1213
|
+
tp.Float('a').must_equal 1.0
|
1214
|
+
end
|
1215
|
+
end
|