form_input 0.9.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/LICENSE +19 -0
- data/README.md +3160 -0
- data/Rakefile +19 -0
- data/example/controllers/ramaze/press_release.rb +104 -0
- data/example/controllers/ramaze/profile.rb +38 -0
- data/example/controllers/sinatra/press_release.rb +114 -0
- data/example/controllers/sinatra/profile.rb +39 -0
- data/example/forms/change_password_form.rb +17 -0
- data/example/forms/login_form.rb +14 -0
- data/example/forms/lost_password_form.rb +14 -0
- data/example/forms/new_password_form.rb +15 -0
- data/example/forms/password_form.rb +18 -0
- data/example/forms/press_release_form.rb +153 -0
- data/example/forms/profile_form.rb +21 -0
- data/example/forms/signup_form.rb +25 -0
- data/example/views/press_release.slim +65 -0
- data/example/views/profile.slim +28 -0
- data/example/views/snippets/form_block.slim +27 -0
- data/example/views/snippets/form_chunked.slim +25 -0
- data/example/views/snippets/form_hidden.slim +21 -0
- data/example/views/snippets/form_panel.slim +89 -0
- data/form_input.gemspec +32 -0
- data/lib/form_input/core.rb +1165 -0
- data/lib/form_input/localize.rb +49 -0
- data/lib/form_input/r18n/cs.yml +97 -0
- data/lib/form_input/r18n/en.yml +70 -0
- data/lib/form_input/r18n/pl.yml +122 -0
- data/lib/form_input/r18n/sk.yml +120 -0
- data/lib/form_input/r18n.rb +163 -0
- data/lib/form_input/steps.rb +365 -0
- data/lib/form_input/types.rb +176 -0
- data/lib/form_input/version.rb +12 -0
- data/lib/form_input.rb +5 -0
- data/test/helper.rb +21 -0
- data/test/localize/en.yml +63 -0
- data/test/r18n/cs.yml +60 -0
- data/test/r18n/xx.yml +51 -0
- data/test/reference/cs.txt +352 -0
- data/test/reference/cs.yml +14 -0
- data/test/reference/en.txt +76 -0
- data/test/reference/en.yml +8 -0
- data/test/reference/pl.txt +440 -0
- data/test/reference/pl.yml +16 -0
- data/test/reference/sk.txt +352 -0
- data/test/reference/sk.yml +14 -0
- data/test/test_core.rb +1272 -0
- data/test/test_localize.rb +27 -0
- data/test/test_r18n.rb +373 -0
- data/test/test_steps.rb +482 -0
- data/test/test_types.rb +307 -0
- metadata +145 -0
data/test/test_core.rb
ADDED
@@ -0,0 +1,1272 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
require 'form_input/core'
|
6
|
+
require 'rack/test'
|
7
|
+
|
8
|
+
class TestForm < FormInput
|
9
|
+
param! :query, :q
|
10
|
+
param :email, "Email",
|
11
|
+
form_title: "Your email",
|
12
|
+
error_title: "email address",
|
13
|
+
match: /@/,
|
14
|
+
type: :email
|
15
|
+
param :age,
|
16
|
+
min: 1,
|
17
|
+
max: 200,
|
18
|
+
filter: ->{ Integer( self, 10 ) rescue self },
|
19
|
+
class: Integer,
|
20
|
+
tag: :filter
|
21
|
+
param :rate,
|
22
|
+
inf: 0,
|
23
|
+
sup: 1,
|
24
|
+
reject: [ /[a-z]/i, /[-+]/ ],
|
25
|
+
tags: ->{ [ :filter, :float ] },
|
26
|
+
tag: :mix,
|
27
|
+
disabled: true
|
28
|
+
param :text, 1000,
|
29
|
+
min_bytesize: 2,
|
30
|
+
max_bytesize: 1999,
|
31
|
+
filter: nil
|
32
|
+
param :password, "Password",
|
33
|
+
min_size: 6,
|
34
|
+
max_size: 16,
|
35
|
+
match: [ /[A-Z]/, /[a-z]/, /\d/ ],
|
36
|
+
msg: 'Password must contain one lowercase and one uppercase letter and one digit',
|
37
|
+
type: :password do
|
38
|
+
chomp
|
39
|
+
end
|
40
|
+
array :opts,
|
41
|
+
min_count: 2,
|
42
|
+
max_count: 3,
|
43
|
+
match: /\A[01]\z/,
|
44
|
+
check: ->{ report( "Only one option may be set" ) unless value.one?{ |x| x.to_i == 1 } }
|
45
|
+
hash :on,
|
46
|
+
min_count: 2,
|
47
|
+
max_count: 4,
|
48
|
+
match: /\A\d\z/,
|
49
|
+
type: :hidden,
|
50
|
+
test: ->( value ){ report( "%p value is too large" ) if value.to_i > 8 }
|
51
|
+
end
|
52
|
+
|
53
|
+
class TestFormInputApp
|
54
|
+
def content( request )
|
55
|
+
form = TestForm.new( request )
|
56
|
+
if form.valid?
|
57
|
+
form.url_query
|
58
|
+
else
|
59
|
+
form.error_messages.join( ':' )
|
60
|
+
end
|
61
|
+
end
|
62
|
+
def call( env )
|
63
|
+
request = Rack::Request.new( env )
|
64
|
+
response = Rack::Response.new
|
65
|
+
response.write content( request )
|
66
|
+
response.finish
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe FormInput do
|
71
|
+
|
72
|
+
VALID_PARAMS = [
|
73
|
+
[ 'q=2', q: 2 ],
|
74
|
+
[ 'q=-', q: "\n-\n" ],
|
75
|
+
[ 'q=%2B', q: " + " ],
|
76
|
+
[ 'q=a+b', q: " a b " ],
|
77
|
+
[ 'q=a+b', q: " \t\r\na \t\r\n b\r\n\t " ],
|
78
|
+
[ 'q=1&email=foo%40bar.com', email: 'foo@bar.com' ],
|
79
|
+
[ 'q=1&age=12&rate=0.3', age: 12, rate: 0.3 ],
|
80
|
+
[ 'q=1&age=1&rate=0.00001', age: 1, rate: '0.00001' ],
|
81
|
+
[ 'q=1&age=200&rate=0.99999', age: 200, rate: '0.99999' ],
|
82
|
+
[ 'q=1&text=%22%27%3C%3E%26%3B%23%40%25+%09%0D%0A%2B', text: "\"'<>&;#\@% \t\r\n+" ],
|
83
|
+
[ 'q=1&text=aa', text: "aa" ],
|
84
|
+
[ 'q=1&text=' + 'a' * 1000, text: "a" * 1000 ],
|
85
|
+
[ 'q=1', text: nil ],
|
86
|
+
[ 'q=1', text: "" ],
|
87
|
+
[ 'q=1&text=++', text: " " ],
|
88
|
+
[ 'q=1', email: nil ],
|
89
|
+
[ 'q=1', email: "" ],
|
90
|
+
[ 'q=1', email: " " ],
|
91
|
+
[ 'q=1&password=Abc123', password: "Abc123" ],
|
92
|
+
[ 'q=1&password=Abc123', password: "Abc123\n" ],
|
93
|
+
[ 'q=1&password=+Abc123+', password: " Abc123 " ],
|
94
|
+
[ 'q=1&password=0123456789abcdeF', password: "0123456789abcdeF" ],
|
95
|
+
[ 'q=1', password: nil ],
|
96
|
+
[ 'q=1', password: "" ],
|
97
|
+
[ 'q=1&password=+aA1+%09', password: " aA1 \t\r\n" ],
|
98
|
+
[ 'q=1&password=+aA1+%09', password: " aA1 \t\n" ],
|
99
|
+
[ 'q=1&password=+aA1+%09', password: " aA1 \t\r" ],
|
100
|
+
[ 'q=1&password=+aA1+%09%0D%0A', password: " aA1 \t\r\n\r\n" ],
|
101
|
+
[ 'q=1&password=+aA1+%09%0A', password: " aA1 \t\n\n" ],
|
102
|
+
[ 'q=1&password=+aA1+%09%0D', password: " aA1 \t\r\r" ],
|
103
|
+
[ 'q=1&opts[]=0&opts[]=1', opts: [ 0, 1 ] ],
|
104
|
+
[ 'q=1&opts[]=0&opts[]=1&opts[]=0', opts: [ 0, 1, 0 ] ],
|
105
|
+
[ 'q=1&on[0]=1&on[2]=8', on: { 0 => 1, 2 => 8 } ],
|
106
|
+
]
|
107
|
+
|
108
|
+
INVALID_PARAMS = [
|
109
|
+
[ 'q is required', q: nil ],
|
110
|
+
[ 'q is required', q: "" ],
|
111
|
+
[ 'q is required', q: " \t\r\n " ],
|
112
|
+
[ 'q is not a string', q: [ 10 ] ],
|
113
|
+
[ 'q is not a string', q: { "x" => "y" } ],
|
114
|
+
[ 'q must use valid encoding', q: 255.chr.force_encoding( 'UTF-8' ) ],
|
115
|
+
[ 'q is required', q: "\u{0000}" ], # Because strip strips \0 as well.
|
116
|
+
[ 'q may not contain invalid characters', q: "a\u{0000}b" ],
|
117
|
+
[ 'q may not contain invalid characters', q: "\u{0001}" ],
|
118
|
+
[ 'q may not contain invalid characters', q: "\u{2029}" ],
|
119
|
+
[ 'email address like this is not valid', email: 'abc' ],
|
120
|
+
[ 'email address may have at most 255 characters', email: 'a@' + 'a' * 254 ],
|
121
|
+
[ 'email address may have at most 255 bytes', email: 'á@' + 'a' * 253 ],
|
122
|
+
[ 'age like this is not valid', age: 0.9 ],
|
123
|
+
[ 'age must be at least 1', age: 0 ],
|
124
|
+
[ 'age may be at most 200', age: 201 ],
|
125
|
+
[ 'rate like this is not allowed', rate: '0.9e10' ],
|
126
|
+
[ 'rate like this is not allowed', rate: '-10' ],
|
127
|
+
[ 'rate must be greater than 0', rate: 0 ],
|
128
|
+
[ 'rate must be less than 1', rate: 1 ],
|
129
|
+
[ 'text must have at least 2 bytes', text: " " ],
|
130
|
+
[ 'text must have at least 2 bytes', text: "a" ],
|
131
|
+
[ 'text may have at most 1000 characters', text: "a" * 1001 ],
|
132
|
+
[ 'text may have at most 1999 bytes', text: "á" * 1000 ],
|
133
|
+
[ 'Password must contain one lowercase and one uppercase letter and one digit', password: "abc123" ],
|
134
|
+
[ 'Password must contain one lowercase and one uppercase letter and one digit', password: "ABC123" ],
|
135
|
+
[ 'Password must contain one lowercase and one uppercase letter and one digit', password: "abcABC" ],
|
136
|
+
[ 'Password must have at least 6 characters', password: " \t\r\n" ],
|
137
|
+
[ 'Password must have at least 6 characters', password: "Abc12" ],
|
138
|
+
[ 'Password may have at most 16 characters', password: "0123456789abcdefG" ],
|
139
|
+
[ 'opts are not an array', opts: "" ],
|
140
|
+
[ 'opts are not an array', opts: " " ],
|
141
|
+
[ 'opts are not an array', opts: "x" ],
|
142
|
+
[ 'opts are not an array', opts: { 1 => 2 } ],
|
143
|
+
[ 'opts contain invalid value', opts: [ 1, { 0 => 1 } ] ],
|
144
|
+
[ 'opts must have at least 2 elements', opts: [ 0 ] ],
|
145
|
+
[ 'opts may have at most 3 elements', opts: [ 0, 1, 0, 0 ] ],
|
146
|
+
[ 'Only one option may be set', opts: [ 0, 1, 1 ] ],
|
147
|
+
[ 'opts like this is not valid', opts: [ 1, 2, 3 ] ],
|
148
|
+
[ 'on are not a hash', on: "" ],
|
149
|
+
[ 'on are not a hash', on: " " ],
|
150
|
+
[ 'on are not a hash', on: "x" ],
|
151
|
+
[ 'on are not a hash', on: [ 2 ] ],
|
152
|
+
[ 'on contain invalid key', on: { "k" => 1, 2 => 3 } ],
|
153
|
+
[ 'on contain invalid key', on: { "0b0" => 1, 2 => 3 } ],
|
154
|
+
[ 'on contain invalid key', on: { "0x0" => 1, 2 => 3 } ],
|
155
|
+
[ 'on contain invalid key', on: { "foo" => 1, "bar" => 3 } ],
|
156
|
+
[ 'on contain too small key', on: { -1 => 1, 2 => 3 } ],
|
157
|
+
[ 'on contain too large key', on: { ( 1 << 64 ) => 1, 2 => 3 } ],
|
158
|
+
[ 'on contain invalid value', on: { 0 => 1, 2 => { 3 => 4 } } ],
|
159
|
+
[ 'on contain invalid value', on: { 0 => 1, 2 => [ 3 ] } ],
|
160
|
+
[ 'on must have at least 2 elements', on: { 1 => 1 } ],
|
161
|
+
[ 'on may have at most 4 elements', on: { 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5 } ],
|
162
|
+
[ 'on like this is not valid', on: { 0 => 1, 2 => 2000 } ],
|
163
|
+
[ 'on like this is not valid', on: { 0 => 1, 2 => "z" } ],
|
164
|
+
[ 'on value is too large', on: { 0 => 9, 2 => 9 } ],
|
165
|
+
]
|
166
|
+
|
167
|
+
extend Rack::Test::Methods
|
168
|
+
|
169
|
+
def app
|
170
|
+
TestFormInputApp.new
|
171
|
+
end
|
172
|
+
|
173
|
+
def request( query )
|
174
|
+
Rack::Request.new( Rack::MockRequest.env_for( query ) )
|
175
|
+
end
|
176
|
+
|
177
|
+
def names( params )
|
178
|
+
params.map{ |x| x && x.name }
|
179
|
+
end
|
180
|
+
|
181
|
+
should 'provide request parameters' do
|
182
|
+
for result, params in VALID_PARAMS
|
183
|
+
post( '/form?q=1', params ).body.should == result
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
should 'detect invalid parameters' do
|
188
|
+
for result, params in INVALID_PARAMS
|
189
|
+
post( '/form?q=1', params ).body.should == result
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
should 'complain about incorrect parameter definition' do
|
194
|
+
->{ TestForm.param :x, "test", "test" }.should.raise( ArgumentError )
|
195
|
+
->{ TestForm.param :x, { type: :email }, :extra }.should.raise( ArgumentError )
|
196
|
+
->{ TestForm.param :x, { type: :email }, nil }.should.raise( ArgumentError )
|
197
|
+
|
198
|
+
->{ TestForm.param :query }.should.raise( ArgumentError )
|
199
|
+
->{ TestForm.array! :opts }.should.raise( ArgumentError )
|
200
|
+
|
201
|
+
->{ TestForm.param :params }.should.raise( ArgumentError )
|
202
|
+
->{ TestForm.param :errors }.should.raise( ArgumentError )
|
203
|
+
|
204
|
+
->{ TestForm.copy nil }.should.raise( ArgumentError )
|
205
|
+
->{ TestForm.copy :foo }.should.raise( ArgumentError )
|
206
|
+
->{ TestForm.copy Object }.should.raise( ArgumentError )
|
207
|
+
->{ TestForm.copy TestForm }.should.raise( ArgumentError )
|
208
|
+
->{ TestForm.copy TestForm[ :query ] }.should.raise( ArgumentError )
|
209
|
+
end
|
210
|
+
|
211
|
+
should 'be cloned and copied properly' do
|
212
|
+
f = TestForm.new
|
213
|
+
f.report( :password, "error" )
|
214
|
+
f.errors_for( :password ).should == [ "error" ]
|
215
|
+
f.errors_for( :text ).should == []
|
216
|
+
c = f.clone
|
217
|
+
c.should.not.equal f
|
218
|
+
d = f.dup
|
219
|
+
d.should.not.equal f
|
220
|
+
c.errors_for( :password ).should == [ "error" ]
|
221
|
+
c.errors_for( :text ).should == []
|
222
|
+
d.errors_for( :password ).should == []
|
223
|
+
d.errors_for( :text ).should == []
|
224
|
+
f.report( :password, "orig" )
|
225
|
+
c.report( :password, "clone" )
|
226
|
+
d.report( :password, "copy" )
|
227
|
+
f.report( :text, "Orig" )
|
228
|
+
c.report( :text, "Clone" )
|
229
|
+
d.report( :text, "Copy" )
|
230
|
+
f.errors_for( :password ).should == [ "error", "orig" ]
|
231
|
+
c.errors_for( :password ).should == [ "error", "clone" ]
|
232
|
+
d.errors_for( :password ).should == [ "copy" ]
|
233
|
+
f.errors_for( :text ).should == [ "Orig" ]
|
234
|
+
c.errors_for( :text ).should == [ "Clone" ]
|
235
|
+
d.errors_for( :text ).should == [ "Copy" ]
|
236
|
+
end
|
237
|
+
|
238
|
+
should 'be frozen properly' do
|
239
|
+
f = TestForm.new
|
240
|
+
f.should.not.be.frozen
|
241
|
+
f.freeze
|
242
|
+
f.should.be.frozen
|
243
|
+
f.should.be.invalid
|
244
|
+
f.param( :query ).should.be.invalid
|
245
|
+
f.query.should.be.nil
|
246
|
+
|
247
|
+
->{ f.query = "x" }.should.raise( RuntimeError )
|
248
|
+
->{ f[ :query ] = "y" }.should.raise( RuntimeError )
|
249
|
+
->{ f.set( query: "z" ) }.should.raise( RuntimeError )
|
250
|
+
->{ f.clear }.should.raise( RuntimeError )
|
251
|
+
->{ f.clear( :query ) }.should.raise( RuntimeError )
|
252
|
+
->{ f.report( :query, "error" ) }.should.raise( RuntimeError )
|
253
|
+
->{ f.validate! }.should.raise( RuntimeError )
|
254
|
+
->{ f.validate }.should.not.raise
|
255
|
+
->{ f.validate? }.should.not.raise
|
256
|
+
|
257
|
+
f.clone.should.be.frozen
|
258
|
+
f.clone.should.be.invalid
|
259
|
+
|
260
|
+
->{ f.clone.query = "x" }.should.raise( RuntimeError )
|
261
|
+
->{ f.clone[ :query ] = "y" }.should.raise( RuntimeError )
|
262
|
+
->{ f.clone.set( query: "z" ) }.should.raise( RuntimeError )
|
263
|
+
->{ f.clone.clear }.should.raise( RuntimeError )
|
264
|
+
->{ f.clone.clear( :query ) }.should.raise( RuntimeError )
|
265
|
+
->{ f.clone.report( :query, "error" ) }.should.raise( RuntimeError )
|
266
|
+
->{ f.clone.validate! }.should.raise( RuntimeError )
|
267
|
+
->{ f.clone.validate }.should.not.raise
|
268
|
+
->{ f.clone.validate? }.should.not.raise
|
269
|
+
|
270
|
+
f.dup.should.not.be.frozen
|
271
|
+
f.dup.should.be.invalid
|
272
|
+
|
273
|
+
->{ f.dup.query = "x" }.should.not.raise
|
274
|
+
->{ f.dup[ :query ] = "y" }.should.not.raise
|
275
|
+
->{ f.dup.set( query: "z" ) }.should.not.raise
|
276
|
+
->{ f.dup.clear }.should.not.raise
|
277
|
+
->{ f.dup.clear( :query ) }.should.not.raise
|
278
|
+
->{ f.dup.report( :query, "error" ) }.should.not.raise
|
279
|
+
->{ f.dup.validate! }.should.not.raise
|
280
|
+
->{ f.dup.validate }.should.not.raise
|
281
|
+
->{ f.dup.validate? }.should.not.raise
|
282
|
+
|
283
|
+
f.query.should.be.nil
|
284
|
+
end
|
285
|
+
|
286
|
+
should 'support form inheritance' do
|
287
|
+
c = Class.new( TestForm ).param :extra
|
288
|
+
names( c.new.params ).should == [ :query, :email, :age, :rate, :text, :password, :opts, :on, :extra ]
|
289
|
+
end
|
290
|
+
|
291
|
+
should 'support parameter copying' do
|
292
|
+
c = Class.new( FormInput )
|
293
|
+
c.param :first
|
294
|
+
c.copy TestForm
|
295
|
+
c.param :last
|
296
|
+
names( c.new.params ).should == [ :first, :query, :email, :age, :rate, :text, :password, :opts, :on, :last ]
|
297
|
+
|
298
|
+
c = Class.new( FormInput )
|
299
|
+
c.param :first
|
300
|
+
c.copy TestForm[ :email ]
|
301
|
+
c.param :last
|
302
|
+
names( c.new.params ).should == [ :first, :email, :last ]
|
303
|
+
|
304
|
+
c = Class.new( FormInput )
|
305
|
+
c.param :first
|
306
|
+
c.copy TestForm[ :password, :age ]
|
307
|
+
c.param :last
|
308
|
+
names( c.new.params ).should == [ :first, :password, :age, :last ]
|
309
|
+
end
|
310
|
+
|
311
|
+
should 'allow changing options when copying parameters' do
|
312
|
+
c = Class.new( FormInput )
|
313
|
+
c.copy TestForm[ :query ]
|
314
|
+
c[ :query ].should.be.required
|
315
|
+
|
316
|
+
c = Class.new( FormInput )
|
317
|
+
c.copy TestForm[ :query ], required: false
|
318
|
+
c[ :query ].should.not.be.required
|
319
|
+
|
320
|
+
c = Class.new( FormInput )
|
321
|
+
c.copy TestForm, required: false
|
322
|
+
c[ :query ].should.not.be.required
|
323
|
+
|
324
|
+
c = Class.new( FormInput )
|
325
|
+
c.copy TestForm[ :query ], name: nil, code: nil, title: nil
|
326
|
+
p = c[ :query ]
|
327
|
+
p.name.should == :query
|
328
|
+
p.code.should == :q
|
329
|
+
p.title.should == nil
|
330
|
+
|
331
|
+
c = Class.new( FormInput )
|
332
|
+
c.copy TestForm[ :password ], name: nil, code: nil, title: nil
|
333
|
+
p = c[ :password ]
|
334
|
+
p.name.should == :password
|
335
|
+
p.code.should == :password
|
336
|
+
p.title.should == nil
|
337
|
+
|
338
|
+
c = Class.new( FormInput )
|
339
|
+
c.copy TestForm[ :email ], name: :foo, code: :bar, title: "FooBar"
|
340
|
+
p = c[ :foo ]
|
341
|
+
p.name.should == :foo
|
342
|
+
p.code.should == :bar
|
343
|
+
p.title.should == "FooBar"
|
344
|
+
end
|
345
|
+
|
346
|
+
should 'support dynamic options' do
|
347
|
+
c = Class.new( FormInput )
|
348
|
+
c.class_eval "def limit ; 5 ; end"
|
349
|
+
c.param :s, max_size: ->{ form.limit }
|
350
|
+
c.array :a, max_count: ->{ form.limit }
|
351
|
+
|
352
|
+
->{ c[ :s ][ :max_size ] }.should.raise NoMethodError
|
353
|
+
->{ c[ :a ][ :max_count ] }.should.raise NoMethodError
|
354
|
+
|
355
|
+
f = c.new( s: "123456" )
|
356
|
+
f.param( :s )[ :max_size ].should == 5
|
357
|
+
f.param( :a )[ :max_count ].should == 5
|
358
|
+
f.error_messages.should == [ "s may have at most 5 characters" ]
|
359
|
+
end
|
360
|
+
|
361
|
+
should 'convert to/from internal value format' do
|
362
|
+
c = Class.new( FormInput )
|
363
|
+
c.param :str
|
364
|
+
c.param :int, filter: ->{ to_i }, class: Integer
|
365
|
+
c.param :int2, filter: ->{ Integer( self, 10 ) rescue self }, class: Integer,
|
366
|
+
check: ->{ report( "%p must be odd" ) unless value.odd? }
|
367
|
+
c.param :float, filter: ->{ to_f }, class: Float
|
368
|
+
c.param :float2, filter: ->{ Float( self ) rescue self }, class: Float
|
369
|
+
c.param :date, filter: ->{ Date.parse( self ) rescue self }, format: ->{ strftime( '%m/%d/%Y' ) }, class: Date
|
370
|
+
c.param :time, filter: ->{ Time.parse( self ) rescue self }, format: ->{ strftime( '%Y-%m-%d %H:%M:%S' ) }, class: Time
|
371
|
+
c.param :bool, filter: ->{ self == 'true' unless empty? }, class: [ TrueClass, FalseClass ]
|
372
|
+
c.param :str2, filter: ->{ downcase.reverse }, format: ->{ reverse.upcase rescue self }
|
373
|
+
c.param :arr, filter: ->{ split( ',' ) }, format: ->{ join( ',' ) rescue self }, class: Array
|
374
|
+
c.param :hsh, filter: ->{ Hash[ scan( /(\d+):(\d+)/ ) ] }, format: ->{ map{ |k,v| "#{k}:#{v}" }.join( ',' ) rescue self }, class: Hash
|
375
|
+
|
376
|
+
f = c.new( request( "?str=1.5&int=1.5&float=1.5&date=2011-12-31&time=31.12.2000+10:24:05&bool=true&str2=Abc&arr=a,b&hsh=1:2,3:4" ) )
|
377
|
+
f.should.be.valid
|
378
|
+
f.to_h.should == f.to_hash
|
379
|
+
f.to_hash.should == {
|
380
|
+
str: "1.5",
|
381
|
+
int: 1,
|
382
|
+
float: 1.5,
|
383
|
+
date: Date.new( 2011, 12, 31 ),
|
384
|
+
time: Time.new( 2000, 12, 31, 10, 24, 05 ),
|
385
|
+
bool: true,
|
386
|
+
str2: "cba",
|
387
|
+
arr: [ "a", "b" ],
|
388
|
+
hsh: { "1" => "2", "3" => "4" },
|
389
|
+
}
|
390
|
+
f.url_params.should == {
|
391
|
+
str: "1.5",
|
392
|
+
int: "1",
|
393
|
+
float: "1.5",
|
394
|
+
date: "12/31/2011",
|
395
|
+
time: "2000-12-31 10:24:05",
|
396
|
+
bool: "true",
|
397
|
+
str2: "ABC",
|
398
|
+
arr: "a,b",
|
399
|
+
hsh: "1:2,3:4",
|
400
|
+
}
|
401
|
+
f.url_query.should == "str=1.5&int=1&float=1.5&date=12%2F31%2F2011&time=2000-12-31+10%3A24%3A05&bool=true&str2=ABC&arr=a%2Cb&hsh=1%3A2%2C3%3A4"
|
402
|
+
|
403
|
+
f = c.new( request( "?str=a&int=b&float=c&date=d&time=e&bool=f" ) )
|
404
|
+
f.should.be.invalid
|
405
|
+
names( f.invalid_params ).should == [ :date, :time ]
|
406
|
+
f.error_messages.should == [ "date like this is not valid", "time like this is not valid" ]
|
407
|
+
f.to_h.should == f.to_hash
|
408
|
+
f.to_hash.should == {
|
409
|
+
str: "a",
|
410
|
+
int: 0,
|
411
|
+
float: 0,
|
412
|
+
date: "d",
|
413
|
+
time: "e",
|
414
|
+
bool: false,
|
415
|
+
}
|
416
|
+
f.url_params.should == {
|
417
|
+
str: "a",
|
418
|
+
int: "0",
|
419
|
+
float: "0.0",
|
420
|
+
date: "d",
|
421
|
+
time: "e",
|
422
|
+
bool: "false",
|
423
|
+
}
|
424
|
+
f.url_query.should == "str=a&int=0&float=0.0&date=d&time=e&bool=false"
|
425
|
+
|
426
|
+
f = c.new( request( "?arr=&hsh=" ) )
|
427
|
+
f.arr.should == []
|
428
|
+
f.hsh.should == {}
|
429
|
+
names( f.incorrect_params ).should == []
|
430
|
+
names( f.invalid_params ).should == []
|
431
|
+
f.to_hash.should == {}
|
432
|
+
f.url_params.should == {}
|
433
|
+
f.url_query.should == ""
|
434
|
+
|
435
|
+
f = c.new( request( "?int=1&int2=1&float=1.5&float2=1.5" ) )
|
436
|
+
f.should.be.valid
|
437
|
+
f.to_hash.should == { int: 1, int2: 1, float: 1.5, float2: 1.5 }
|
438
|
+
f.url_params.should == { int: "1", int2: "1", float: "1.5", float2: "1.5" }
|
439
|
+
f.url_query.should == "int=1&int2=1&float=1.5&float2=1.5"
|
440
|
+
|
441
|
+
f = c.new( request( "?int=1&int2=1.5&float=foo&float2=foo" ) )
|
442
|
+
f.should.be.invalid
|
443
|
+
names( f.invalid_params ).should == [ :int2, :float2 ]
|
444
|
+
f.error_messages.should == [ "int2 like this is not valid", "float2 like this is not valid" ]
|
445
|
+
f.to_hash.should == { int: 1, int2: "1.5", float: 0, float2: "foo" }
|
446
|
+
f.url_params.should == { int: "1", int2: "1.5", float: "0.0", float2: "foo" }
|
447
|
+
f.url_query.should == "int=1&int2=1.5&float=0.0&float2=foo"
|
448
|
+
|
449
|
+
f = c.new( request( "?int=&int2=&float=&float2=" ) )
|
450
|
+
f.should.be.valid
|
451
|
+
names( f.invalid_params ).should == []
|
452
|
+
f.error_messages.should == []
|
453
|
+
f.to_hash.should == { int: 0, float: 0 }
|
454
|
+
f.url_params.should == { int: "0", float: "0.0" }
|
455
|
+
f.url_query.should == "int=0&float=0.0"
|
456
|
+
|
457
|
+
f = c.new( request( "?int=0x0a&int2=0x0a" ) )
|
458
|
+
f.should.be.invalid
|
459
|
+
names( f.invalid_params ).should == [ :int2 ]
|
460
|
+
f.error_messages.should == [ "int2 like this is not valid" ]
|
461
|
+
f.to_hash.should == { int: 0, int2: "0x0a" }
|
462
|
+
f.url_params.should == { int: "0", int2: "0x0a" }
|
463
|
+
f.url_query.should == "int=0&int2=0x0a"
|
464
|
+
|
465
|
+
f = c.new( request( "?int2=2" ) )
|
466
|
+
f.should.be.invalid
|
467
|
+
names( f.invalid_params ).should == [ :int2 ]
|
468
|
+
f.error_messages.should == [ "int2 must be odd" ]
|
469
|
+
f.to_hash.should == { int2: 2 }
|
470
|
+
f.url_params.should == { int2: "2" }
|
471
|
+
f.url_query.should == "int2=2"
|
472
|
+
|
473
|
+
p = c[ :int ]
|
474
|
+
p.format_value( nil ).should == ""
|
475
|
+
p.format_value( 10 ).should == "10"
|
476
|
+
p.format_value( "foo" ).should == "foo"
|
477
|
+
|
478
|
+
p = c[ :float ]
|
479
|
+
p.format_value( nil ).should == ""
|
480
|
+
p.format_value( 10 ).should == "10"
|
481
|
+
p.format_value( 10.0 ).should == "10.0"
|
482
|
+
p.format_value( "foo" ).should == "foo"
|
483
|
+
|
484
|
+
p = c[ :date ]
|
485
|
+
p.format_value( nil ).should == ""
|
486
|
+
p.format_value( Time.at( 123456789 ).utc ).should == "11/29/1973"
|
487
|
+
p.format_value( "foo" ).should == "foo"
|
488
|
+
|
489
|
+
p = c[ :time ]
|
490
|
+
p.format_value( nil ).should == ""
|
491
|
+
p.format_value( Time.at( 123456789 ).utc ).should == "1973-11-29 21:33:09"
|
492
|
+
p.format_value( "foo" ).should == "foo"
|
493
|
+
|
494
|
+
p = c[ :bool ]
|
495
|
+
p.format_value( nil ).should == ""
|
496
|
+
p.format_value( true ).should == "true"
|
497
|
+
p.format_value( false ).should == "false"
|
498
|
+
p.format_value( "foo" ).should == "foo"
|
499
|
+
|
500
|
+
p = c[ :str ]
|
501
|
+
p.format_value( nil ).should == ""
|
502
|
+
p.format_value( true ).should == "true"
|
503
|
+
p.format_value( false ).should == "false"
|
504
|
+
p.format_value( 10 ).should == "10"
|
505
|
+
p.format_value( 10.0 ).should == "10.0"
|
506
|
+
p.format_value( "abc" ).should == "abc"
|
507
|
+
|
508
|
+
p = c[ :str2 ]
|
509
|
+
p.format_value( nil ).should == ""
|
510
|
+
p.format_value( true ).should == "true"
|
511
|
+
p.format_value( false ).should == "false"
|
512
|
+
p.format_value( 10 ).should == "10"
|
513
|
+
p.format_value( 10.0 ).should == "10.0"
|
514
|
+
p.format_value( "abc" ).should == "CBA"
|
515
|
+
|
516
|
+
p = c[ :arr ]
|
517
|
+
p.format_value( nil ).should == ""
|
518
|
+
p.format_value( [] ).should == ""
|
519
|
+
p.format_value( true ).should == "true"
|
520
|
+
p.format_value( false ).should == "false"
|
521
|
+
p.format_value( 10 ).should == "10"
|
522
|
+
p.format_value( 10.0 ).should == "10.0"
|
523
|
+
p.format_value( "abc" ).should == "abc"
|
524
|
+
|
525
|
+
p = c[ :hsh ]
|
526
|
+
p.format_value( nil ).should == ""
|
527
|
+
p.format_value( {} ).should == ""
|
528
|
+
p.format_value( true ).should == "true"
|
529
|
+
p.format_value( false ).should == "false"
|
530
|
+
p.format_value( 10 ).should == "10"
|
531
|
+
p.format_value( 10.0 ).should == "10.0"
|
532
|
+
p.format_value( "abc" ).should == "abc"
|
533
|
+
end
|
534
|
+
|
535
|
+
should 'support input transformation' do
|
536
|
+
c = Class.new( FormInput )
|
537
|
+
c.array :a
|
538
|
+
|
539
|
+
f = c.new( request( "?a[]=abc&a[]=&a[]=123&a[]=" ) )
|
540
|
+
f.a.should == [ "abc", "", "123", "" ]
|
541
|
+
|
542
|
+
c = Class.new( FormInput )
|
543
|
+
c.array :a, filter: ->{ reverse }, transform: ->{ reject{ |x| x.empty? } }
|
544
|
+
|
545
|
+
f = c.new( request( "?a[]=abc&a[]=&a[]=123&a[]=" ) )
|
546
|
+
f.a.should == [ "cba", "321" ]
|
547
|
+
|
548
|
+
f = c.new( a: [ "abc", "", "123" ] )
|
549
|
+
f.a.should == [ "abc", "", "123" ]
|
550
|
+
end
|
551
|
+
|
552
|
+
should 'support string hash keys when allowed' do
|
553
|
+
c = Class.new( FormInput )
|
554
|
+
c.hash :h
|
555
|
+
|
556
|
+
f = c.new( request( "?h[0]=a&h[1]=b&h[2]=c" ) )
|
557
|
+
f.should.be.valid
|
558
|
+
f.h.should == { 0 => 'a', 1 => 'b', 2 => 'c' }
|
559
|
+
f.url_query.should == "h[0]=a&h[1]=b&h[2]=c"
|
560
|
+
|
561
|
+
f = c.new( request( "?h[a]=a&h[b]=b&h[c]=c" ) )
|
562
|
+
f.should.be.invalid
|
563
|
+
f.error_messages.should == [ "h contain invalid key" ]
|
564
|
+
f.h.should == { 'a' => 'a', 'b' => 'b', 'c' => 'c' }
|
565
|
+
f.url_query.should == "h[a]=a&h[b]=b&h[c]=c"
|
566
|
+
|
567
|
+
c = Class.new( FormInput )
|
568
|
+
c.hash :h, match_key: /\A\d+\z/
|
569
|
+
|
570
|
+
f = c.new( request( "?h[0]=a&h[1]=b&h[2]=c" ) )
|
571
|
+
f.should.be.valid
|
572
|
+
f.h.should == { 0 => 'a', 1 => 'b', 2 => 'c' }
|
573
|
+
f.url_query.should == "h[0]=a&h[1]=b&h[2]=c"
|
574
|
+
|
575
|
+
f = c.new( request( "?h[a]=a&h[b]=b&h[c]=c" ) )
|
576
|
+
f.should.be.invalid
|
577
|
+
f.error_messages.should == [ "h contain invalid key" ]
|
578
|
+
f.h.should == { 'a' => 'a', 'b' => 'b', 'c' => 'c' }
|
579
|
+
f.url_query.should == "h[a]=a&h[b]=b&h[c]=c"
|
580
|
+
|
581
|
+
c = Class.new( FormInput )
|
582
|
+
c.hash :h, match_key: /\A[a-z]\z/
|
583
|
+
|
584
|
+
f = c.new( request( "?h[0]=a&h[1]=b&h[2]=c" ) )
|
585
|
+
f.should.be.invalid
|
586
|
+
f.error_messages.should == [ "h contain invalid key" ]
|
587
|
+
f.h.should == { 0 => 'a', 1 => 'b', 2 => 'c' }
|
588
|
+
f.url_query.should == "h[0]=a&h[1]=b&h[2]=c"
|
589
|
+
|
590
|
+
f = c.new( request( "?h[a]=a&h[b]=b&h[c]=c" ) )
|
591
|
+
f.should.be.valid
|
592
|
+
f.h.should == { 'a' => 'a', 'b' => 'b', 'c' => 'c' }
|
593
|
+
f.url_query.should == "h[a]=a&h[b]=b&h[c]=c"
|
594
|
+
|
595
|
+
c = Class.new( FormInput )
|
596
|
+
c.hash :h, match_key: ->{ [ /\A[a-z]+\z/i, /^[A-Z]/, /[A-Z]$/ ] }
|
597
|
+
|
598
|
+
f = c.new( request( "?h[A]=a&h[Bar]=b&h[baZ]=c" ) )
|
599
|
+
f.should.be.invalid
|
600
|
+
f.error_messages.should == [ "h contain invalid key" ]
|
601
|
+
f.h.should == { 'A' => 'a', 'Bar' => 'b', 'baZ' => 'c' }
|
602
|
+
f.url_query.should == "h[A]=a&h[Bar]=b&h[baZ]=c"
|
603
|
+
|
604
|
+
f = c.new( request( "?h[A]=a&h[BAR]=b&h[BaZ]=c" ) )
|
605
|
+
f.should.be.valid
|
606
|
+
f.h.should == { 'A' => 'a', 'BAR' => 'b', 'BaZ' => 'c' }
|
607
|
+
f.url_query.should == "h[A]=a&h[BAR]=b&h[BaZ]=c"
|
608
|
+
end
|
609
|
+
|
610
|
+
should 'support select parameters' do
|
611
|
+
c = Class.new( FormInput )
|
612
|
+
c.param :single, data: ->{ 2.times.map{ |i| [ i, ( 65 + i ).chr ] } }, class: Integer do to_i end
|
613
|
+
c.array :multi, data: ->{ 4.times.map{ |i| [ i, ( 65 + i ).chr ] } }, class: Integer do to_i end
|
614
|
+
c.param :x, filter: ->{ to_i }, class: Integer
|
615
|
+
|
616
|
+
f = c.new( single: 1, multi: [ 1, 3 ], x: 5 )
|
617
|
+
f.should.be.valid
|
618
|
+
f.to_hash.should == { single: 1, multi: [ 1, 3 ], x: 5 }
|
619
|
+
f.url_params.should == { single: "1", multi: [ "1", "3" ], x: "5" }
|
620
|
+
f.url_query.should == "single=1&multi[]=1&multi[]=3&x=5"
|
621
|
+
|
622
|
+
p = f.param( :single )
|
623
|
+
p.data.should == [ [ 0, "A" ], [ 1, "B" ] ]
|
624
|
+
p.code.should == :single
|
625
|
+
p.form_name.should == "single"
|
626
|
+
p.form_value.should == "1"
|
627
|
+
p.selected?( nil ).should.be.false
|
628
|
+
p.selected?( 0 ).should.be.false
|
629
|
+
p.selected?( 1 ).should.be.true
|
630
|
+
p.selected?( 2 ).should.be.false
|
631
|
+
|
632
|
+
p = f.param( :multi )
|
633
|
+
p.data.should == [ [ 0, "A" ], [ 1, "B" ], [ 2, "C" ], [ 3, "D" ] ]
|
634
|
+
p.code.should == :multi
|
635
|
+
p.form_name.should == "multi[]"
|
636
|
+
p.form_value.should == [ "1", "3" ]
|
637
|
+
p.selected?( nil ).should.be.false
|
638
|
+
p.selected?( 0 ).should.be.false
|
639
|
+
p.selected?( 1 ).should.be.true
|
640
|
+
p.selected?( 2 ).should.be.false
|
641
|
+
p.selected?( 3 ).should.be.true
|
642
|
+
|
643
|
+
p = f.param( :x )
|
644
|
+
p.data.should == []
|
645
|
+
p.code.should == :x
|
646
|
+
p.form_name.should == "x"
|
647
|
+
p.form_value.should == "5"
|
648
|
+
|
649
|
+
f = c.new( request( "?single=0&multi[]=0&multi[]=2&x=3" ) ) ;
|
650
|
+
f.should.be.valid
|
651
|
+
f.to_hash.should == { single: 0, multi: [ 0, 2 ], x: 3 }
|
652
|
+
f.url_params.should == { single: "0", multi: [ "0", "2" ], x: "3" }
|
653
|
+
f.url_query.should == "single=0&multi[]=0&multi[]=2&x=3"
|
654
|
+
|
655
|
+
f = c.new( request( "?single=5&multi[]=5" ) ) ;
|
656
|
+
f.should.be.valid
|
657
|
+
f.to_hash.should == { single: 5, multi: [ 5 ] }
|
658
|
+
f.url_params.should == { single: "5", multi: [ "5" ] }
|
659
|
+
f.url_query.should == "single=5&multi[]=5"
|
660
|
+
|
661
|
+
f = c.new( request( "" ) ) ;
|
662
|
+
f.should.be.valid
|
663
|
+
f.to_hash.should == {}
|
664
|
+
f.url_params.should == {}
|
665
|
+
f.url_query.should == ""
|
666
|
+
end
|
667
|
+
|
668
|
+
should 'classify parameters' do
|
669
|
+
f = TestForm.new( query: "x", text: "abc", password: nil, email: " " )
|
670
|
+
names( f.params ).should == [ :query, :email, :age, :rate, :text, :password, :opts, :on ]
|
671
|
+
names( f.params ).should == f.params_names
|
672
|
+
|
673
|
+
names( f.named_params ).should == []
|
674
|
+
names( f.named_params( :query ) ).should == [ :query ]
|
675
|
+
names( f.named_params( :text, :email ) ).should == [ :text, :email ]
|
676
|
+
names( f.named_params( :age, :age ) ).should == [ :age, :age ]
|
677
|
+
|
678
|
+
names( f.correct_params ).should == [ :query, :email, :age, :rate, :text, :password, :opts, :on ]
|
679
|
+
names( f.incorrect_params ).should == []
|
680
|
+
|
681
|
+
names( f.filled_params ).should == [ :query, :email, :text ]
|
682
|
+
names( f.empty_params ).should == [ :age, :rate, :password, :opts, :on ]
|
683
|
+
names( f.blank_params ).should == [ :email, :age, :rate, :password, :opts, :on ]
|
684
|
+
|
685
|
+
names( f.tagged_params ).should == [ :age, :rate ]
|
686
|
+
names( f.untagged_params ).should == [ :query, :email, :text, :password, :opts, :on ]
|
687
|
+
|
688
|
+
names( f.tagged_params( :filter ) ).should == [ :age, :rate ]
|
689
|
+
names( f.untagged_params( :filter ) ).should == [ :query, :email, :text, :password, :opts, :on ]
|
690
|
+
|
691
|
+
names( f.tagged_params( :float ) ).should == [ :rate ]
|
692
|
+
names( f.untagged_params( :float ) ).should == [ :query, :email, :age, :text, :password, :opts, :on ]
|
693
|
+
|
694
|
+
names( f.tagged_params( :filter, :float ) ).should == [ :age, :rate ]
|
695
|
+
names( f.untagged_params( :filter, :float ) ).should == [ :query, :email, :text, :password, :opts, :on ]
|
696
|
+
|
697
|
+
names( f.tagged_params( :foo ) ).should == []
|
698
|
+
names( f.untagged_params( :foo ) ).should == [ :query, :email, :age, :rate, :text, :password, :opts, :on ]
|
699
|
+
|
700
|
+
names( f.tagged_params( :float, :foo ) ).should == [ :rate ]
|
701
|
+
names( f.untagged_params( :float, :foo ) ).should == [ :query, :email, :age, :text, :password, :opts, :on ]
|
702
|
+
|
703
|
+
names( f.tagged_params( [] ) ).should == []
|
704
|
+
names( f.untagged_params( [] ) ).should == [ :query, :email, :age, :rate, :text, :password, :opts, :on ]
|
705
|
+
|
706
|
+
names( f.tagged_params( [ :filter ] ) ).should == [ :age, :rate ]
|
707
|
+
names( f.untagged_params( [ :filter ] ) ).should == [ :query, :email, :text, :password, :opts, :on ]
|
708
|
+
|
709
|
+
names( f.tagged_params( [ :float ] ) ).should == [ :rate ]
|
710
|
+
names( f.untagged_params( [ :float ] ) ).should == [ :query, :email, :age, :text, :password, :opts, :on ]
|
711
|
+
|
712
|
+
names( f.tagged_params( [ :filter, :float ] ) ).should == [ :age, :rate ]
|
713
|
+
names( f.untagged_params( [ :filter, :float ] ) ).should == [ :query, :email, :text, :password, :opts, :on ]
|
714
|
+
|
715
|
+
names( f.tagged_params( [ :foo ] ) ).should == []
|
716
|
+
names( f.untagged_params( [ :foo ] ) ).should == [ :query, :email, :age, :rate, :text, :password, :opts, :on ]
|
717
|
+
|
718
|
+
names( f.tagged_params( [ :float, :foo ] ) ).should == [ :rate ]
|
719
|
+
names( f.untagged_params( [ :float, :foo ] ) ).should == [ :query, :email, :age, :text, :password, :opts, :on ]
|
720
|
+
|
721
|
+
names( f.required_params ).should == [ :query ]
|
722
|
+
names( f.optional_params ).should == [ :email, :age, :rate, :text, :password, :opts, :on ]
|
723
|
+
|
724
|
+
names( f.disabled_params ).should == [ :rate ]
|
725
|
+
names( f.enabled_params ).should == [ :query, :email, :age, :text, :password, :opts, :on ]
|
726
|
+
|
727
|
+
names( f.hidden_params ).should == [ :on ]
|
728
|
+
names( f.ignored_params ).should == []
|
729
|
+
names( f.visible_params ).should == [ :query, :email, :age, :rate, :text, :password, :opts ]
|
730
|
+
|
731
|
+
names( f.array_params ).should == [ :opts ]
|
732
|
+
names( f.hash_params ).should == [ :on ]
|
733
|
+
names( f.scalar_params ).should == [ :query, :email, :age, :rate, :text, :password ]
|
734
|
+
|
735
|
+
names( f.invalid_params ).should == [ :email ]
|
736
|
+
names( f.valid_params ).should == [ :query, :age, :rate, :text, :password, :opts, :on ]
|
737
|
+
end
|
738
|
+
|
739
|
+
should 'expose details via parameters' do
|
740
|
+
f = TestForm.new( query: "x", text: "abc", :email => " " )
|
741
|
+
|
742
|
+
p = f.param( :query )
|
743
|
+
p.form.should == f
|
744
|
+
p.name.should == :query
|
745
|
+
p.code.should == :q
|
746
|
+
p.type.should == :text
|
747
|
+
p.title.should == nil
|
748
|
+
p.form_title.should == "q"
|
749
|
+
p.error_title.should == "q"
|
750
|
+
p.opts.should == { required: true, filter: FormInput::DEFAULT_FILTER, max_size: 255, max_bytesize: 255 }
|
751
|
+
p[ :form_title ].should == nil
|
752
|
+
p[ :max_size ].should == 255
|
753
|
+
p.value.should == "x"
|
754
|
+
p.form_value.should == "x"
|
755
|
+
p.should.be.correct
|
756
|
+
p.should.not.be.incorrect
|
757
|
+
p.should.not.be.blank
|
758
|
+
p.should.not.be.empty
|
759
|
+
p.should.be.filled
|
760
|
+
p.should.be.valid
|
761
|
+
p.should.not.be.invalid
|
762
|
+
p.should.be.required
|
763
|
+
p.should.not.be.optional
|
764
|
+
p.should.not.be.disabled
|
765
|
+
p.should.be.enabled
|
766
|
+
p.should.not.be.hidden
|
767
|
+
p.should.not.be.ignored
|
768
|
+
p.should.be.visible
|
769
|
+
p.should.not.be.array
|
770
|
+
p.should.not.be.hash
|
771
|
+
p.should.be.scalar
|
772
|
+
p.should.not.be.tagged
|
773
|
+
p.should.be.untagged
|
774
|
+
p.errors.should == []
|
775
|
+
p.error.should == nil
|
776
|
+
p.tags.should == []
|
777
|
+
|
778
|
+
p = f.param( :email )
|
779
|
+
p.form.should == f
|
780
|
+
p.name.should == :email
|
781
|
+
p.code.should == :email
|
782
|
+
p.type.should == :email
|
783
|
+
p.title.should == "Email"
|
784
|
+
p.form_title.should == "Your email"
|
785
|
+
p.error_title.should == "email address"
|
786
|
+
p.value.should == " "
|
787
|
+
p.form_value.should == " "
|
788
|
+
p.should.be.correct
|
789
|
+
p.should.not.be.incorrect
|
790
|
+
p.should.be.blank
|
791
|
+
p.should.not.be.empty
|
792
|
+
p.should.be.filled
|
793
|
+
p.should.not.be.valid
|
794
|
+
p.should.be.invalid
|
795
|
+
p.should.not.be.required
|
796
|
+
p.should.be.optional
|
797
|
+
p.should.not.be.disabled
|
798
|
+
p.should.be.enabled
|
799
|
+
p.should.not.be.hidden
|
800
|
+
p.should.not.be.ignored
|
801
|
+
p.should.be.visible
|
802
|
+
p.should.not.be.array
|
803
|
+
p.should.not.be.hash
|
804
|
+
p.should.be.scalar
|
805
|
+
p.should.not.be.tagged
|
806
|
+
p.should.be.untagged
|
807
|
+
p.errors.should == [ "email address like this is not valid" ]
|
808
|
+
p.error.should == "email address like this is not valid"
|
809
|
+
p.tags.should == []
|
810
|
+
|
811
|
+
p = f.param( :rate )
|
812
|
+
p.value.should == nil
|
813
|
+
p.form_value.should == ""
|
814
|
+
p.should.be.blank
|
815
|
+
p.should.be.empty
|
816
|
+
p.should.not.be.filled
|
817
|
+
p.should.be.disabled
|
818
|
+
p.should.not.be.enabled
|
819
|
+
p[ :tag ].should == :mix
|
820
|
+
p[ :tags ].should == [ :filter, :float ]
|
821
|
+
p.tags.should == [ :mix, :filter, :float ]
|
822
|
+
p.should.be.tagged
|
823
|
+
p.should.not.be.untagged
|
824
|
+
p.should.be.tagged( :filter )
|
825
|
+
p.should.not.be.untagged( :filter )
|
826
|
+
p.should.be.tagged( :foo, :float )
|
827
|
+
p.should.not.be.untagged( :foo, :float )
|
828
|
+
p.should.not.be.tagged( :foo )
|
829
|
+
p.should.be.untagged( :foo )
|
830
|
+
p.should.not.be.tagged( [] )
|
831
|
+
p.should.be.untagged( [] )
|
832
|
+
p.should.be.tagged( [ :filter ] )
|
833
|
+
p.should.not.be.untagged( [ :filter ] )
|
834
|
+
p.should.be.tagged( [ :foo, :float ] )
|
835
|
+
p.should.not.be.untagged( [ :foo, :float ] )
|
836
|
+
p.should.not.be.tagged( [ :foo ] )
|
837
|
+
p.should.be.untagged( [ :foo ] )
|
838
|
+
|
839
|
+
p = f.param( :opts )
|
840
|
+
p.value.should == nil
|
841
|
+
p.form_value.should == []
|
842
|
+
p.should.be.blank
|
843
|
+
p.should.be.empty
|
844
|
+
p.should.not.be.filled
|
845
|
+
p.should.be.array
|
846
|
+
p.should.not.be.hash
|
847
|
+
p.should.not.be.scalar
|
848
|
+
|
849
|
+
p = f.param( :on )
|
850
|
+
p.opts.values_at( :min_key, :max_key ).should == [ 0, 18446744073709551615 ]
|
851
|
+
p.value.should == nil
|
852
|
+
p.form_value.should == {}
|
853
|
+
p.should.be.blank
|
854
|
+
p.should.be.empty
|
855
|
+
p.should.not.be.filled
|
856
|
+
p.should.not.be.array
|
857
|
+
p.should.be.hash
|
858
|
+
p.should.not.be.scalar
|
859
|
+
p.type.should == :hidden
|
860
|
+
p.should.be.hidden
|
861
|
+
p.should.not.be.ignored
|
862
|
+
p.should.not.be.visible
|
863
|
+
end
|
864
|
+
|
865
|
+
should 'support both new and derived forms' do
|
866
|
+
f = TestForm.new
|
867
|
+
f.should.be.empty
|
868
|
+
f.url_query.should == ""
|
869
|
+
|
870
|
+
f = TestForm.new( request( "" ) )
|
871
|
+
f.should.be.empty
|
872
|
+
f.url_query.should == ""
|
873
|
+
|
874
|
+
f = TestForm.new( request( "?q=10" ) )
|
875
|
+
f.should.not.be.empty
|
876
|
+
f.url_query.should == "q=10"
|
877
|
+
|
878
|
+
f = TestForm.new( query: "x" )
|
879
|
+
f.should.not.be.empty
|
880
|
+
f.url_query.should == "q=x"
|
881
|
+
|
882
|
+
f.set( email: "a@b", text: "foo" )
|
883
|
+
f.should.not.be.empty
|
884
|
+
f.url_query.should == "q=x&email=a%40b&text=foo"
|
885
|
+
|
886
|
+
f.except( :email ).url_query.should == "q=x&text=foo"
|
887
|
+
f.except( :email, :query ).url_query.should == "text=foo"
|
888
|
+
f.except().url_query.should == "q=x&email=a%40b&text=foo"
|
889
|
+
f.except( [ :email ] ).url_query.should == "q=x&text=foo"
|
890
|
+
f.except( [ :email, :query ] ).url_query.should == "text=foo"
|
891
|
+
f.except( [] ).url_query.should == "q=x&email=a%40b&text=foo"
|
892
|
+
|
893
|
+
f.only( :email ).url_query.should == "email=a%40b"
|
894
|
+
f.only( :email, :query ).url_query.should == "q=x&email=a%40b"
|
895
|
+
f.only().url_query.should == ""
|
896
|
+
f.only( [ :email ] ).url_query.should == "email=a%40b"
|
897
|
+
f.only( [ :email, :query ] ).url_query.should == "q=x&email=a%40b"
|
898
|
+
f.only( [] ).url_query.should == ""
|
899
|
+
|
900
|
+
f.clear( :text )
|
901
|
+
f.should.not.be.empty
|
902
|
+
f.url_query.should == "q=x&email=a%40b"
|
903
|
+
f.clear( f.required_params )
|
904
|
+
f.should.not.be.empty
|
905
|
+
f.url_query.should == "email=a%40b"
|
906
|
+
f.clear
|
907
|
+
f.should.be.empty
|
908
|
+
f.url_query.should == ""
|
909
|
+
|
910
|
+
f = TestForm.new( { age: 2, query: "x" }, { rate: 1, query: "y" } )
|
911
|
+
f.url_query.should == "q=y&age=2&rate=1"
|
912
|
+
|
913
|
+
f = TestForm.new( request( "?q=10&age=3" ), query: "y", rate: 0 )
|
914
|
+
f.url_query.should == "q=y&age=3&rate=0"
|
915
|
+
|
916
|
+
f = TestForm.new( { query: "x", age: 5 }, request( "?rate=1&q=10" ) )
|
917
|
+
f.url_query.should == "q=10&age=5&rate=1"
|
918
|
+
|
919
|
+
f = TestForm.from_request( request( "?q=+%30&age=0" ) )
|
920
|
+
f.to_hash.should == { query: "0", age: 0 }
|
921
|
+
f.url_query.should == "q=0&age=0"
|
922
|
+
|
923
|
+
f = TestForm.from_params( q: "+%30", age: "0" )
|
924
|
+
f.to_hash.should == { query: "+%30", age: 0 }
|
925
|
+
f.url_query.should == "q=%2B%2530&age=0"
|
926
|
+
|
927
|
+
f = TestForm.from_hash( query: "+%30", age: "0" )
|
928
|
+
f.to_hash.should == { query: "+%30", age: "0" }
|
929
|
+
f.url_query.should == "q=%2B%2530&age=0"
|
930
|
+
end
|
931
|
+
|
932
|
+
should 'provide direct access to values' do
|
933
|
+
f = TestForm.new( email: "a@b", text: "foo" )
|
934
|
+
|
935
|
+
f.email.should == "a@b"
|
936
|
+
f.email = "x@y"
|
937
|
+
f.email.should == "x@y"
|
938
|
+
|
939
|
+
f[ :text ].should == "foo"
|
940
|
+
f[ :text ] = "bar"
|
941
|
+
f[ :text ].should == "bar"
|
942
|
+
|
943
|
+
f[ :query, :text ].should == [ nil, "bar" ]
|
944
|
+
f[ :text, :email ].should == [ "bar", "x@y" ]
|
945
|
+
end
|
946
|
+
|
947
|
+
should 'guard against typos in parameter names' do
|
948
|
+
f = TestForm.new
|
949
|
+
|
950
|
+
f.param( :typo ).should == nil
|
951
|
+
f.named_params( :typo ).should == [ nil ]
|
952
|
+
f.named_params( :typo, :missing ).should == [ nil, nil ]
|
953
|
+
|
954
|
+
->{ f.set( typo: 10 ) }.should.raise( NoMethodError )
|
955
|
+
->{ f.clear( :typo ) }.should.raise( ArgumentError )
|
956
|
+
->{ f.except( :typo ) }.should.raise( ArgumentError )
|
957
|
+
->{ f.except( [ :typo ] ) }.should.raise( ArgumentError )
|
958
|
+
->{ f.only( :typo ) }.should.raise( ArgumentError )
|
959
|
+
->{ f.only( [ :typo ] ) }.should.raise( ArgumentError )
|
960
|
+
|
961
|
+
->{ f.typo }.should.raise( NoMethodError )
|
962
|
+
->{ f.typo = 10 }.should.raise( NoMethodError )
|
963
|
+
->{ f[ :typo ] }.should.raise( NoMethodError )
|
964
|
+
->{ f[ :typo ] = 10 }.should.raise( NoMethodError )
|
965
|
+
->{ f[ :query, :typo ] }.should.raise( NoMethodError )
|
966
|
+
|
967
|
+
->{ f.valid?( :typo ) }.should.raise( ArgumentError )
|
968
|
+
->{ f.valid?( :query, :typo ) }.should.raise( ArgumentError )
|
969
|
+
->{ f.valid?( [ :typo ] ) }.should.raise( ArgumentError )
|
970
|
+
->{ f.valid?( [ :query, :typo ] ) }.should.raise( ArgumentError )
|
971
|
+
->{ f.invalid?( :typo ) }.should.raise( ArgumentError )
|
972
|
+
->{ f.invalid?( :query, :typo ) }.should.raise( ArgumentError )
|
973
|
+
->{ f.invalid?( [ :typo ] ) }.should.raise( ArgumentError )
|
974
|
+
->{ f.invalid?( [ :query, :typo ] ) }.should.raise( ArgumentError )
|
975
|
+
->{ f.valid }.should.raise( ArgumentError )
|
976
|
+
->{ f.valid( :typo ) }.should.raise( ArgumentError )
|
977
|
+
->{ f.valid( :query, :typo ) }.should.raise( ArgumentError )
|
978
|
+
->{ f.valid( [ :typo ] ) }.should.raise( ArgumentError )
|
979
|
+
->{ f.valid( [ :query, :typo ] ) }.should.raise( ArgumentError )
|
980
|
+
end
|
981
|
+
|
982
|
+
should 'not overwrite original values via derived forms' do
|
983
|
+
f = TestForm.new( query: "x" )
|
984
|
+
f.query.should == "x"
|
985
|
+
f[ :query ].should == "x"
|
986
|
+
|
987
|
+
f.dup.query = "y"
|
988
|
+
f.query.should == "x"
|
989
|
+
f[ :query ].should == "x"
|
990
|
+
|
991
|
+
f.only( :query ).query = "y"
|
992
|
+
f.query.should == "x"
|
993
|
+
f[ :query ].should == "x"
|
994
|
+
|
995
|
+
f.only( :query )[ :query ] = "y"
|
996
|
+
f.query.should == "x"
|
997
|
+
f[ :query ].should == "x"
|
998
|
+
|
999
|
+
f.except( :query ).query = "y"
|
1000
|
+
f.query.should == "x"
|
1001
|
+
f[ :query ].should == "x"
|
1002
|
+
|
1003
|
+
f.except( :query )[ :query ] = "y"
|
1004
|
+
f.query.should == "x"
|
1005
|
+
f[ :query ].should == "x"
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
should 'handle non string values gracefully' do
|
1009
|
+
f = TestForm.new( query: true, age: 3, rate: 0.35, text: false, opts: [], on: {} )
|
1010
|
+
->{ f.validate }.should.not.raise
|
1011
|
+
f.to_hash.should == { query: true, age: 3, rate: 0.35, text: false }
|
1012
|
+
f.url_params.should == { q: "true", age: "3", rate: "0.35", text: "false" }
|
1013
|
+
f.url_query.should == "q=true&age=3&rate=0.35&text=false"
|
1014
|
+
names( f.incorrect_params ).should == [ :query, :rate, :text ]
|
1015
|
+
|
1016
|
+
f = TestForm.new( opts: 1 )
|
1017
|
+
->{ f.validate }.should.not.raise
|
1018
|
+
f.to_hash.should == { opts: 1 }
|
1019
|
+
f.url_params.should == { opts: [ "1" ] }
|
1020
|
+
f.url_query.should == "opts[]=1"
|
1021
|
+
names( f.incorrect_params ).should == [ :opts ]
|
1022
|
+
|
1023
|
+
f = TestForm.new( opts: [ 2.5, true ] )
|
1024
|
+
->{ f.validate }.should.not.raise
|
1025
|
+
f.to_hash.should == { opts: [ 2.5, true ] }
|
1026
|
+
f.url_params.should == { opts: [ "2.5", "true" ] }
|
1027
|
+
f.url_query.should == "opts[]=2.5&opts[]=true"
|
1028
|
+
names( f.incorrect_params ).should == []
|
1029
|
+
|
1030
|
+
f = TestForm.new( opts: { "foo" => 10, true => false } )
|
1031
|
+
->{ f.validate }.should.not.raise
|
1032
|
+
f.to_hash.should == { opts: { "foo" => 10, true => false } }
|
1033
|
+
f.url_params.should == { opts: [ '["foo", 10]', '[true, false]' ] }
|
1034
|
+
f.url_query.should == "opts[]=%5B%22foo%22%2C+10%5D&opts[]=%5Btrue%2C+false%5D"
|
1035
|
+
names( f.incorrect_params ).should == [ :opts ]
|
1036
|
+
|
1037
|
+
f = TestForm.new( on: 1 )
|
1038
|
+
->{ f.validate }.should.not.raise
|
1039
|
+
f.to_hash.should == { on: 1 }
|
1040
|
+
f.url_params.should == { on: { "1" => "" } }
|
1041
|
+
f.url_query.should == "on[1]="
|
1042
|
+
names( f.incorrect_params ).should == [ :on ]
|
1043
|
+
|
1044
|
+
f = TestForm.new( on: { 0 => 1, 2 => 3.4 } )
|
1045
|
+
->{ f.validate }.should.not.raise
|
1046
|
+
f.to_hash.should == { on: { 0 => 1, 2 => 3.4 } }
|
1047
|
+
f.url_params.should == { on: { "0" => "1", "2" => "3.4" } }
|
1048
|
+
f.url_query.should == "on[0]=1&on[2]=3.4"
|
1049
|
+
names( f.incorrect_params ).should == []
|
1050
|
+
|
1051
|
+
f = TestForm.new( on: [ [ 10, 20 ], [ true, false ] ] )
|
1052
|
+
->{ f.validate }.should.not.raise
|
1053
|
+
f.to_hash.should == { on: [ [ 10, 20 ], [ true, false ] ] }
|
1054
|
+
f.url_params.should == { on: { "10" => "20", "true" => "false" } }
|
1055
|
+
f.url_query.should == "on[10]=20&on[true]=false"
|
1056
|
+
names( f.incorrect_params ).should == [ :on ]
|
1057
|
+
|
1058
|
+
f = TestForm.new( on: [ 1, true, false ] )
|
1059
|
+
->{ f.validate }.should.not.raise
|
1060
|
+
f.to_hash.should == { on: [ 1, true, false ] }
|
1061
|
+
f.url_params.should == { on: { "1" => "", "true" => "", "false" => "" } }
|
1062
|
+
f.url_query.should == "on[1]=&on[true]=&on[false]="
|
1063
|
+
names( f.incorrect_params ).should == [ :on ]
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
should 'handle invalid encoding gracefully' do
|
1067
|
+
s = 255.chr.force_encoding( 'UTF-8' )
|
1068
|
+
|
1069
|
+
f = TestForm.new( query: s )
|
1070
|
+
->{ f.validate }.should.not.raise
|
1071
|
+
f.should.not.be.valid
|
1072
|
+
f.error_messages.should == [ "q must use valid encoding" ]
|
1073
|
+
f.param( :query ).should.not.be.blank
|
1074
|
+
f.to_hash.should == { query: s }
|
1075
|
+
f.url_params.should == { q: s }
|
1076
|
+
f.url_query.should == "q=%FF"
|
1077
|
+
|
1078
|
+
f = TestForm.new( Rack::Request.new( Rack::MockRequest.env_for( "?q=%ff" ) ) )
|
1079
|
+
->{ f.validate }.should.not.raise
|
1080
|
+
f.should.not.be.valid
|
1081
|
+
f.error_messages.should == [ "q must use valid encoding" ]
|
1082
|
+
f.param( :query ).should.not.be.blank
|
1083
|
+
f.to_hash.should == { query: s.dup.force_encoding( 'BINARY' ) }
|
1084
|
+
f.url_params.should == { q: s.dup.force_encoding( 'BINARY' ) }
|
1085
|
+
f.url_query.should == "q=%FF"
|
1086
|
+
end
|
1087
|
+
|
1088
|
+
should 'make it easy to create URLs' do
|
1089
|
+
f = TestForm.new( query: "x", opts: [ 0, 0, 1 ], on: { 0 => 1 }, age: 10, email: nil, password: "", text: " " )
|
1090
|
+
f.url_params.should == { q: "x", age: "10", text: " ", opts: [ "0", "0", "1" ], on: { "0" => "1" } }
|
1091
|
+
f.url_query.should == "q=x&age=10&text=+&opts[]=0&opts[]=0&opts[]=1&on[0]=1"
|
1092
|
+
f.extend_url( "" ).should == "?q=x&age=10&text=+&opts[]=0&opts[]=0&opts[]=1&on[0]=1"
|
1093
|
+
f.extend_url( "/" ).should == "/?q=x&age=10&text=+&opts[]=0&opts[]=0&opts[]=1&on[0]=1"
|
1094
|
+
f.extend_url( "/foo" ).should == "/foo?q=x&age=10&text=+&opts[]=0&opts[]=0&opts[]=1&on[0]=1"
|
1095
|
+
f.extend_url( "/foo?x" ).should == "/foo?x&q=x&age=10&text=+&opts[]=0&opts[]=0&opts[]=1&on[0]=1"
|
1096
|
+
f.extend_url( URI.parse( "/foo" ) ).should == "/foo?q=x&age=10&text=+&opts[]=0&opts[]=0&opts[]=1&on[0]=1"
|
1097
|
+
f.extend_url( URI.parse( "/foo?x" ) ).should == "/foo?x&q=x&age=10&text=+&opts[]=0&opts[]=0&opts[]=1&on[0]=1"
|
1098
|
+
|
1099
|
+
f = TestForm.new
|
1100
|
+
f.url_params.should == {}
|
1101
|
+
f.url_query.should == ""
|
1102
|
+
f.extend_url( "" ).should == ""
|
1103
|
+
f.extend_url( "/" ).should == "/"
|
1104
|
+
f.extend_url( "/foo" ).should == "/foo"
|
1105
|
+
f.extend_url( "/foo?x" ).should == "/foo?x"
|
1106
|
+
f.extend_url( URI.parse( "/foo" ) ).should == "/foo"
|
1107
|
+
f.extend_url( URI.parse( "/foo?x" ) ).should == "/foo?x"
|
1108
|
+
|
1109
|
+
f.build_url( "/" ).should == "/"
|
1110
|
+
f.build_url( "/foo", query: "x" ).should == "/foo?q=x"
|
1111
|
+
f.build_url( "/foo?x", query: "x", age: 42 ).should == "/foo?x&q=x&age=42"
|
1112
|
+
end
|
1113
|
+
|
1114
|
+
should 'provide useful error detecting and reporting methods' do
|
1115
|
+
# Create new form every time to test that the validation triggers automatically.
|
1116
|
+
f = ->{ TestForm.new( email: "x", text: "yy" ) }
|
1117
|
+
f[].should.not.be.valid
|
1118
|
+
f[].should.be.invalid
|
1119
|
+
f[].should.be.valid?( :text )
|
1120
|
+
f[].should.not.be.valid?( :email )
|
1121
|
+
f[].should.not.be.valid?( :text, :email )
|
1122
|
+
f[].should.be.valid?( [] )
|
1123
|
+
f[].should.be.valid?( [ :text ] )
|
1124
|
+
f[].should.not.be.valid?( [ :email ] )
|
1125
|
+
f[].should.not.be.valid?( [ :text, :email ] )
|
1126
|
+
f[].should.not.be.invalid?( :text )
|
1127
|
+
f[].should.be.invalid?( :email )
|
1128
|
+
f[].should.be.invalid?( :text, :email )
|
1129
|
+
f[].should.not.be.invalid?( [] )
|
1130
|
+
f[].should.not.be.invalid?( [ :text ] )
|
1131
|
+
f[].should.be.invalid?( [ :email ] )
|
1132
|
+
f[].should.be.invalid?( [ :text, :email ] )
|
1133
|
+
f[].valid( :text ).should == "yy"
|
1134
|
+
f[].valid( :email ).should == nil
|
1135
|
+
f[].valid( :text, :email ).should == nil
|
1136
|
+
f[].valid( :text, :password ).should == [ "yy", nil ]
|
1137
|
+
f[].valid( :text, :text ).should == [ "yy", "yy" ]
|
1138
|
+
f[].errors.should == { query: [ "q is required" ], email: [ "email address like this is not valid" ] }
|
1139
|
+
f[].error_messages.should == [ "q is required", "email address like this is not valid" ]
|
1140
|
+
f[].errors_for( :query ).should == [ "q is required" ]
|
1141
|
+
f[].error_for( :query ).should == "q is required"
|
1142
|
+
f[].errors_for( :password ).should == []
|
1143
|
+
f[].error_for( :password ).should == nil
|
1144
|
+
|
1145
|
+
f = ->{ TestForm.new.report( :query, "msg" ).report( :password, "bad" ) }
|
1146
|
+
f[].should.not.be.valid
|
1147
|
+
f[].should.be.invalid
|
1148
|
+
f[].should.be.valid?( :email )
|
1149
|
+
f[].should.not.be.valid?( :query )
|
1150
|
+
f[].should.not.be.valid?( :email, :query )
|
1151
|
+
f[].should.be.valid?( [] )
|
1152
|
+
f[].should.be.valid?( [ :email ] )
|
1153
|
+
f[].should.not.be.valid?( [ :query ] )
|
1154
|
+
f[].should.not.be.valid?( [ :email, :query ] )
|
1155
|
+
f[].should.not.be.invalid?( :email )
|
1156
|
+
f[].should.be.invalid?( :query )
|
1157
|
+
f[].should.be.invalid?( :email, :query )
|
1158
|
+
f[].should.not.be.invalid?( [] )
|
1159
|
+
f[].should.not.be.invalid?( [ :email ] )
|
1160
|
+
f[].should.be.invalid?( [ :query ] )
|
1161
|
+
f[].should.be.invalid?( [ :email, :query ] )
|
1162
|
+
f[].errors.should == { query: [ "q is required", "msg" ], password: [ "bad" ] }
|
1163
|
+
f[].error_messages.should == [ "q is required", "bad" ]
|
1164
|
+
f[].errors_for( :query ).should == [ "q is required", "msg" ]
|
1165
|
+
f[].error_for( :query ).should == "q is required"
|
1166
|
+
f[].errors_for( :password ).should == [ "bad" ]
|
1167
|
+
f[].error_for( :password ).should == "bad"
|
1168
|
+
|
1169
|
+
f = TestForm.new
|
1170
|
+
f.should.be.invalid
|
1171
|
+
f.set( query: "x" ).should.be.valid
|
1172
|
+
f.should.be.valid
|
1173
|
+
f.except( :query ).should.be.invalid
|
1174
|
+
f.should.be.valid
|
1175
|
+
f.only( :password ).should.be.invalid
|
1176
|
+
f.should.be.valid
|
1177
|
+
f.dup.set( query: "" ).should.be.invalid
|
1178
|
+
f.should.be.valid
|
1179
|
+
|
1180
|
+
f.query = nil
|
1181
|
+
f.should.be.valid
|
1182
|
+
f.validate?.should.be.valid
|
1183
|
+
f.dup.validate?.should.be.invalid
|
1184
|
+
f.validate.should.be.invalid
|
1185
|
+
f.validate!.should.be.invalid
|
1186
|
+
|
1187
|
+
f.query = "x"
|
1188
|
+
f.should.be.invalid
|
1189
|
+
f.validate?.should.be.invalid
|
1190
|
+
f.dup.validate?.should.be.valid
|
1191
|
+
f.validate.should.be.invalid
|
1192
|
+
f.validate!.should.be.valid
|
1193
|
+
|
1194
|
+
f[ :query ] = nil
|
1195
|
+
f.should.be.invalid
|
1196
|
+
f.validate?.should.be.invalid
|
1197
|
+
f.dup.validate?.should.be.invalid
|
1198
|
+
f.validate.should.be.invalid
|
1199
|
+
f.validate!.should.be.invalid
|
1200
|
+
|
1201
|
+
f[ :query ] = "x"
|
1202
|
+
f.should.be.valid
|
1203
|
+
f.validate?.should.be.valid
|
1204
|
+
f.dup.validate?.should.be.valid
|
1205
|
+
f.validate.should.be.valid
|
1206
|
+
f.validate!.should.be.valid
|
1207
|
+
|
1208
|
+
f.clear.should.equal f
|
1209
|
+
f.should.be.invalid
|
1210
|
+
f.validate?.should.be.invalid
|
1211
|
+
f.dup.validate?.should.be.invalid
|
1212
|
+
f.validate.should.be.invalid
|
1213
|
+
f.validate!.should.be.invalid
|
1214
|
+
|
1215
|
+
f.set( query: "x" ).should.equal f
|
1216
|
+
f.should.be.valid
|
1217
|
+
f.validate?.should.be.valid
|
1218
|
+
f.dup.validate?.should.be.valid
|
1219
|
+
f.validate.should.be.valid
|
1220
|
+
f.validate!.should.be.valid
|
1221
|
+
end
|
1222
|
+
|
1223
|
+
should 'support some custom error messages' do
|
1224
|
+
c = Class.new( FormInput )
|
1225
|
+
c.param! :q, match: /A/, reject: /B/
|
1226
|
+
c.copy c[ :q ], name: :c,
|
1227
|
+
required_msg: '%p must be filled in',
|
1228
|
+
match_msg: '%p must contain A',
|
1229
|
+
reject_msg: '%p may not contain B'
|
1230
|
+
f = c.new
|
1231
|
+
f.error_messages.should == [ "q is required", "c must be filled in" ]
|
1232
|
+
f = c.new( q: 'X', c: 'X' )
|
1233
|
+
f.error_messages.should == [ "q like this is not valid", "c must contain A" ]
|
1234
|
+
f = c.new( q: 'BA', c: 'BA' )
|
1235
|
+
f.error_messages.should == [ "q like this is not allowed", "c may not contain B" ]
|
1236
|
+
f = c.new( q: 'A', c: 'A' )
|
1237
|
+
f.error_messages.should.be.empty
|
1238
|
+
end
|
1239
|
+
|
1240
|
+
should 'split parameters into rows as desired' do
|
1241
|
+
c = Class.new( FormInput )
|
1242
|
+
c.param :a
|
1243
|
+
c.param :b, row: 1
|
1244
|
+
c.param :c, row: 1
|
1245
|
+
c.param :d
|
1246
|
+
c.param :e, row: 1
|
1247
|
+
c.param :f, row: 2
|
1248
|
+
c.param :g, row: 2
|
1249
|
+
c.param :h, row: 3
|
1250
|
+
c.param :i, row: 3
|
1251
|
+
c.param :j, row: 3
|
1252
|
+
c.param :k
|
1253
|
+
|
1254
|
+
f = c.new
|
1255
|
+
f.chunked_params.map{ |x| x.is_a?( Array ) ? x.map{ |y| y.name } : x.name }.should == [
|
1256
|
+
:a,
|
1257
|
+
[ :b, :c ],
|
1258
|
+
:d,
|
1259
|
+
:e,
|
1260
|
+
[ :f, :g ],
|
1261
|
+
[ :h, :i, :j ],
|
1262
|
+
:k
|
1263
|
+
]
|
1264
|
+
|
1265
|
+
f = TestForm.new
|
1266
|
+
f.chunked_params.should == f.params
|
1267
|
+
f.chunked_params( f.scalar_params ).should == f.scalar_params
|
1268
|
+
end
|
1269
|
+
|
1270
|
+
end
|
1271
|
+
|
1272
|
+
# EOF #
|