formeze 3.0.0 → 3.1.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 +5 -5
- data/CHANGES.md +156 -0
- data/LICENSE.txt +1 -6
- data/README.md +12 -19
- data/formeze.gemspec +10 -8
- data/lib/formeze.rb +38 -13
- metadata +12 -66
- data/Rakefile.rb +0 -8
- data/spec/formeze_spec.rb +0 -1018
data/Rakefile.rb
DELETED
data/spec/formeze_spec.rb
DELETED
@@ -1,1018 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'formeze'
|
3
|
-
require 'i18n'
|
4
|
-
require 'mime-types'
|
5
|
-
|
6
|
-
I18n.available_locales = [:en]
|
7
|
-
|
8
|
-
class FormWithField < Formeze::Form
|
9
|
-
field :title
|
10
|
-
end
|
11
|
-
|
12
|
-
describe 'FormWithField' do
|
13
|
-
before do
|
14
|
-
@form = FormWithField.new
|
15
|
-
end
|
16
|
-
|
17
|
-
describe 'title method' do
|
18
|
-
it 'returns nil' do
|
19
|
-
@form.title.must_be_nil
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe 'title equals method' do
|
24
|
-
it 'sets the value of the title attribute' do
|
25
|
-
@form.title = 'Untitled'
|
26
|
-
@form.title.must_equal('Untitled')
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe 'parse method' do
|
31
|
-
it 'sets the value of the title attribute' do
|
32
|
-
@form.parse('title=Untitled')
|
33
|
-
@form.title.must_equal('Untitled')
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'raises an exception when the key is missing' do
|
37
|
-
proc { @form.parse('') }.must_raise(Formeze::KeyError)
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'raises an exception when there are multiple values for the key' do
|
41
|
-
proc { @form.parse('title=foo&title=bar') }.must_raise(Formeze::ValueError)
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'raises an exception when the data contains unexpected keys' do
|
45
|
-
exception = proc { @form.parse('title=Untitled&foo=bar&baz=') }.must_raise(Formeze::KeyError)
|
46
|
-
|
47
|
-
exception.message.must_equal('unexpected form keys: baz, foo')
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'returns self' do
|
51
|
-
@form.parse('title=Untitled').must_equal(@form)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
describe 'fill method' do
|
56
|
-
it 'sets the value of the title attribute when given a hash with symbol keys' do
|
57
|
-
@form.fill({:title => 'Untitled'})
|
58
|
-
@form.title.must_equal('Untitled')
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'sets the value of the title attribute when given an object with a title attribute' do
|
62
|
-
object = Object.new
|
63
|
-
|
64
|
-
def object.title; 'Untitled' end
|
65
|
-
|
66
|
-
@form.fill(object)
|
67
|
-
@form.title.must_equal('Untitled')
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'returns self' do
|
71
|
-
@form.fill({:title => 'Untitled'}).must_equal(@form)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
describe 'FormWithField after parsing valid input' do
|
77
|
-
before do
|
78
|
-
@form = FormWithField.new
|
79
|
-
@form.parse('title=Untitled')
|
80
|
-
end
|
81
|
-
|
82
|
-
describe 'title method' do
|
83
|
-
it 'returns the value of the field' do
|
84
|
-
@form.title.must_equal('Untitled')
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe 'valid query method' do
|
89
|
-
it 'returns true' do
|
90
|
-
@form.valid?.must_equal(true)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
describe 'errors query method' do
|
95
|
-
it 'returns false' do
|
96
|
-
@form.errors?.must_equal(false)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
describe 'errors method' do
|
101
|
-
it 'returns an empty array' do
|
102
|
-
@form.errors.must_equal([])
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
describe 'errors_on query method' do
|
107
|
-
it 'returns false when given the title field name' do
|
108
|
-
@form.errors_on?(:title).must_equal(false)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
describe 'errors_on method' do
|
113
|
-
it 'returns an empty array when given the title field name' do
|
114
|
-
@form.errors_on(:title).must_equal([])
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
describe 'to_h method' do
|
119
|
-
it 'returns a hash containing the field name and its value' do
|
120
|
-
@form.to_h.must_equal({:title => 'Untitled'})
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
describe 'to_hash method' do
|
125
|
-
it 'returns a hash containing the field name and its value' do
|
126
|
-
@form.to_hash.must_equal({:title => 'Untitled'})
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
describe 'FormWithField after parsing blank input' do
|
132
|
-
before do
|
133
|
-
@form = FormWithField.new
|
134
|
-
@form.parse('title=')
|
135
|
-
end
|
136
|
-
|
137
|
-
describe 'valid query method' do
|
138
|
-
it 'returns false' do
|
139
|
-
@form.valid?.must_equal(false)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
describe 'errors query method' do
|
144
|
-
it 'returns true' do
|
145
|
-
@form.errors?.must_equal(true)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
describe 'errors method' do
|
150
|
-
it 'returns an array containing a single error message' do
|
151
|
-
@form.errors.must_be_instance_of(Array)
|
152
|
-
@form.errors.length.must_equal(1)
|
153
|
-
@form.errors.first.to_s.must_equal('Title is required')
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
describe 'errors_on query method' do
|
158
|
-
it 'returns true when given the title field name' do
|
159
|
-
@form.errors_on?(:title).must_equal(true)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
describe 'errors_on method' do
|
164
|
-
it 'returns an array containing a single error message when given the title field name' do
|
165
|
-
errors = @form.errors_on(:title)
|
166
|
-
errors.must_be_instance_of(Array)
|
167
|
-
errors.length.must_equal(1)
|
168
|
-
errors.first.to_s.must_equal('Title is required')
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
describe 'FormWithField after parsing input containing newlines' do
|
174
|
-
before do
|
175
|
-
@form = FormWithField.new
|
176
|
-
@form.parse('title=This+is+a+product.%0AIt+is+very+lovely.')
|
177
|
-
end
|
178
|
-
|
179
|
-
describe 'valid query method' do
|
180
|
-
it 'returns false' do
|
181
|
-
@form.valid?.must_equal(false)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
class FormWithOptionalField < Formeze::Form
|
187
|
-
field :title, :required => false
|
188
|
-
end
|
189
|
-
|
190
|
-
describe 'FormWithOptionalField after parsing blank input' do
|
191
|
-
before do
|
192
|
-
@form = FormWithOptionalField.new
|
193
|
-
@form.parse('title=')
|
194
|
-
end
|
195
|
-
|
196
|
-
describe 'valid query method' do
|
197
|
-
it 'returns true' do
|
198
|
-
@form.valid?.must_equal(true)
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
class FormWithOptionalFieldUsingBlankOption < Formeze::Form
|
204
|
-
field :title, :required => false, :blank => 42
|
205
|
-
end
|
206
|
-
|
207
|
-
describe 'FormWithOptionalFieldUsingBlankOption after parsing blank input' do
|
208
|
-
before do
|
209
|
-
@form = FormWithOptionalFieldUsingBlankOption.new
|
210
|
-
@form.parse('title=')
|
211
|
-
end
|
212
|
-
|
213
|
-
describe 'title method' do
|
214
|
-
it 'returns the value specified by the blank option' do
|
215
|
-
@form.title.must_equal(42)
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
class FormWithFieldThatCanHaveMultipleLines < Formeze::Form
|
221
|
-
field :description, :multiline => true
|
222
|
-
end
|
223
|
-
|
224
|
-
describe 'FormWithFieldThatCanHaveMultipleLines after parsing input containing newlines' do
|
225
|
-
before do
|
226
|
-
@form = FormWithFieldThatCanHaveMultipleLines.new
|
227
|
-
@form.parse('description=This+is+a+product.%0AIt+is+very+lovely.')
|
228
|
-
end
|
229
|
-
|
230
|
-
describe 'valid query method' do
|
231
|
-
it 'returns true' do
|
232
|
-
@form.valid?.must_equal(true)
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
class FormWithMaxLengthField < Formeze::Form
|
238
|
-
field :title, :maxlength => 16
|
239
|
-
end
|
240
|
-
|
241
|
-
describe 'FormWithMaxLengthField after parsing input with too many characters' do
|
242
|
-
before do
|
243
|
-
@form = FormWithMaxLengthField.new
|
244
|
-
@form.parse('title=This+Title+Will+Be+Too+Long')
|
245
|
-
end
|
246
|
-
|
247
|
-
describe 'valid query method' do
|
248
|
-
it 'returns false' do
|
249
|
-
@form.valid?.must_equal(false)
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
class FormWithMinLengthField < Formeze::Form
|
255
|
-
field :title, :minlength => 8
|
256
|
-
end
|
257
|
-
|
258
|
-
describe 'FormWithMinLengthField after parsing input with too few characters' do
|
259
|
-
before do
|
260
|
-
@form = FormWithMinLengthField.new
|
261
|
-
@form.parse('title=Hello')
|
262
|
-
end
|
263
|
-
|
264
|
-
describe 'valid query method' do
|
265
|
-
it 'returns false' do
|
266
|
-
@form.valid?.must_equal(false)
|
267
|
-
end
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
class FormWithFieldThatMustMatchPattern < Formeze::Form
|
272
|
-
field :number, :pattern => /\A\d+\z/
|
273
|
-
end
|
274
|
-
|
275
|
-
describe 'FormWithFieldThatMustMatchPattern after parsing input that matches the pattern' do
|
276
|
-
before do
|
277
|
-
@form = FormWithFieldThatMustMatchPattern.new
|
278
|
-
@form.parse('number=12345')
|
279
|
-
end
|
280
|
-
|
281
|
-
describe 'valid query method' do
|
282
|
-
it 'returns true' do
|
283
|
-
@form.valid?.must_equal(true)
|
284
|
-
end
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
describe 'FormWithFieldThatMustMatchPattern after parsing input that does not match the pattern' do
|
289
|
-
before do
|
290
|
-
@form = FormWithFieldThatMustMatchPattern.new
|
291
|
-
@form.parse('number=notanumber')
|
292
|
-
end
|
293
|
-
|
294
|
-
describe 'valid query method' do
|
295
|
-
it 'returns false' do
|
296
|
-
@form.valid?.must_equal(false)
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
class FormWithFieldThatCanHaveMultipleValues < Formeze::Form
|
302
|
-
field :colour, :multiple => true
|
303
|
-
end
|
304
|
-
|
305
|
-
describe 'FormWithFieldThatCanHaveMultipleValues' do
|
306
|
-
before do
|
307
|
-
@form = FormWithFieldThatCanHaveMultipleValues.new
|
308
|
-
end
|
309
|
-
|
310
|
-
describe 'colour method' do
|
311
|
-
it 'returns nil' do
|
312
|
-
@form.colour.must_be_nil
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
describe 'colour equals method' do
|
317
|
-
it 'adds the argument to the colour attribute array' do
|
318
|
-
@form.colour = 'black'
|
319
|
-
@form.colour.must_include('black')
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
|
-
describe 'parse method' do
|
324
|
-
it 'adds the value to the colour attribute array' do
|
325
|
-
@form.parse('colour=black')
|
326
|
-
@form.colour.must_include('black')
|
327
|
-
end
|
328
|
-
|
329
|
-
it 'does not raise an exception when there are multiple values for the key' do
|
330
|
-
@form.parse('colour=black&colour=white')
|
331
|
-
end
|
332
|
-
|
333
|
-
it 'does not raise an exception when the key is missing' do
|
334
|
-
@form.parse('')
|
335
|
-
end
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
describe 'FormWithFieldThatCanHaveMultipleValues after parsing input with multiple values' do
|
340
|
-
before do
|
341
|
-
@form = FormWithFieldThatCanHaveMultipleValues.new
|
342
|
-
@form.parse('colour=black&colour=white')
|
343
|
-
end
|
344
|
-
|
345
|
-
describe 'colour method' do
|
346
|
-
it 'returns an array containing the values' do
|
347
|
-
@form.colour.must_equal(['black', 'white'])
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
describe 'valid query method' do
|
352
|
-
it 'returns true' do
|
353
|
-
@form.valid?.must_equal(true)
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
|
-
describe 'to_hash method' do
|
358
|
-
it 'returns a hash containing the field name and its array value' do
|
359
|
-
@form.to_hash.must_equal({:colour => %w(black white)})
|
360
|
-
end
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
describe 'FormWithFieldThatCanHaveMultipleValues after parsing input with no values' do
|
365
|
-
before do
|
366
|
-
@form = FormWithFieldThatCanHaveMultipleValues.new
|
367
|
-
@form.parse('')
|
368
|
-
end
|
369
|
-
|
370
|
-
describe 'colour method' do
|
371
|
-
it 'returns nil' do
|
372
|
-
@form.colour.must_be_nil
|
373
|
-
end
|
374
|
-
end
|
375
|
-
|
376
|
-
describe 'valid query method' do
|
377
|
-
it 'returns true' do
|
378
|
-
@form.valid?.must_equal(true)
|
379
|
-
end
|
380
|
-
end
|
381
|
-
end
|
382
|
-
|
383
|
-
class FormWithFieldThatCanOnlyHaveSpecifiedValues < Formeze::Form
|
384
|
-
field :answer, :values => %w(yes no)
|
385
|
-
end
|
386
|
-
|
387
|
-
describe 'FormWithFieldThatCanOnlyHaveSpecifiedValues after parsing input with an invalid value' do
|
388
|
-
before do
|
389
|
-
@form = FormWithFieldThatCanOnlyHaveSpecifiedValues.new
|
390
|
-
@form.parse('answer=maybe')
|
391
|
-
end
|
392
|
-
|
393
|
-
describe 'valid query method' do
|
394
|
-
it 'returns false' do
|
395
|
-
@form.valid?.must_equal(false)
|
396
|
-
end
|
397
|
-
end
|
398
|
-
end
|
399
|
-
|
400
|
-
class FormWithGuardCondition < Formeze::Form
|
401
|
-
field :account_name
|
402
|
-
field :account_vat_number, :defined_if => proc { @business_account }
|
403
|
-
|
404
|
-
def initialize(business_account)
|
405
|
-
@business_account = business_account
|
406
|
-
end
|
407
|
-
end
|
408
|
-
|
409
|
-
describe 'FormWithGuardCondition with business_account set to false' do
|
410
|
-
before do
|
411
|
-
@form = FormWithGuardCondition.new(false)
|
412
|
-
end
|
413
|
-
|
414
|
-
describe 'parse method' do
|
415
|
-
it 'raises an exception when the account_vat_number key is present' do
|
416
|
-
proc { @form.parse('account_name=Something&account_vat_number=123456789') }.must_raise(Formeze::KeyError)
|
417
|
-
end
|
418
|
-
end
|
419
|
-
end
|
420
|
-
|
421
|
-
describe 'FormWithGuardCondition with business_account set to true' do
|
422
|
-
before do
|
423
|
-
@form = FormWithGuardCondition.new(true)
|
424
|
-
end
|
425
|
-
|
426
|
-
describe 'parse method' do
|
427
|
-
it 'raises an exception when the account_vat_number key is missing' do
|
428
|
-
proc { @form.parse('account_name=Something') }.must_raise(Formeze::KeyError)
|
429
|
-
end
|
430
|
-
end
|
431
|
-
end
|
432
|
-
|
433
|
-
describe 'FormWithGuardCondition with business_account set to false after parsing valid input' do
|
434
|
-
before do
|
435
|
-
@form = FormWithGuardCondition.new(false)
|
436
|
-
@form.parse('account_name=Something')
|
437
|
-
end
|
438
|
-
|
439
|
-
describe 'valid query method' do
|
440
|
-
it 'returns true' do
|
441
|
-
@form.valid?.must_equal(true)
|
442
|
-
end
|
443
|
-
end
|
444
|
-
end
|
445
|
-
|
446
|
-
class FormWithHaltingCondition < Formeze::Form
|
447
|
-
field :delivery_address
|
448
|
-
field :same_address, :values => %w(yes no)
|
449
|
-
field :billing_address, :defined_unless => :same_address?
|
450
|
-
|
451
|
-
def same_address?
|
452
|
-
same_address == 'yes'
|
453
|
-
end
|
454
|
-
end
|
455
|
-
|
456
|
-
describe 'FormWithHaltingCondition' do
|
457
|
-
before do
|
458
|
-
@form = FormWithHaltingCondition.new
|
459
|
-
end
|
460
|
-
|
461
|
-
describe 'parse method' do
|
462
|
-
it 'raises an exception when there is an unexpected key' do
|
463
|
-
proc { @form.parse('delivery_address=123+Main+St&same_address=yes&foo=bar') }.must_raise(Formeze::KeyError)
|
464
|
-
end
|
465
|
-
end
|
466
|
-
end
|
467
|
-
|
468
|
-
describe 'FormWithHaltingCondition after parsing input with same_address set and no billing address' do
|
469
|
-
before do
|
470
|
-
@form = FormWithHaltingCondition.new
|
471
|
-
@form.parse('delivery_address=123+Main+St&same_address=yes')
|
472
|
-
end
|
473
|
-
|
474
|
-
describe 'valid query method' do
|
475
|
-
it 'returns true' do
|
476
|
-
@form.valid?.must_equal(true)
|
477
|
-
end
|
478
|
-
end
|
479
|
-
end
|
480
|
-
|
481
|
-
class FormWithOptionalKey < Formeze::Form
|
482
|
-
field :accept_terms, :values => %w(true), :key_required => false
|
483
|
-
end
|
484
|
-
|
485
|
-
describe 'FormWithOptionalKey after parsing input without the key' do
|
486
|
-
before do
|
487
|
-
@form = FormWithOptionalKey.new
|
488
|
-
@form.parse('')
|
489
|
-
end
|
490
|
-
|
491
|
-
describe 'valid query method' do
|
492
|
-
it 'returns true' do
|
493
|
-
@form.valid?.must_equal(true)
|
494
|
-
end
|
495
|
-
end
|
496
|
-
end
|
497
|
-
|
498
|
-
class FormWithOptionalFieldThatCanOnlyHaveSpecifiedValues < Formeze::Form
|
499
|
-
field :size, :required => false, :values => %w(S M L XL)
|
500
|
-
end
|
501
|
-
|
502
|
-
describe 'FormWithOptionalFieldThatCanOnlyHaveSpecifiedValues after parsing blank input' do
|
503
|
-
before do
|
504
|
-
@form = FormWithOptionalFieldThatCanOnlyHaveSpecifiedValues.new
|
505
|
-
@form.parse('size=')
|
506
|
-
end
|
507
|
-
|
508
|
-
describe 'valid query method' do
|
509
|
-
it 'returns true' do
|
510
|
-
@form.valid?.must_equal(true)
|
511
|
-
end
|
512
|
-
end
|
513
|
-
end
|
514
|
-
|
515
|
-
module EmailAddress
|
516
|
-
def self.valid?(address)
|
517
|
-
address.include?('@')
|
518
|
-
end
|
519
|
-
end
|
520
|
-
|
521
|
-
class FormWithCustomEmailValidation < Formeze::Form
|
522
|
-
field :email
|
523
|
-
|
524
|
-
validates :email, &EmailAddress.method(:valid?)
|
525
|
-
end
|
526
|
-
|
527
|
-
describe 'FormWithCustomEmailValidation after parsing invalid input' do
|
528
|
-
before do
|
529
|
-
@form = FormWithCustomEmailValidation.new
|
530
|
-
@form.parse('email=alice')
|
531
|
-
end
|
532
|
-
|
533
|
-
describe 'valid query method' do
|
534
|
-
it 'returns false' do
|
535
|
-
@form.valid?.must_equal(false)
|
536
|
-
end
|
537
|
-
end
|
538
|
-
|
539
|
-
describe 'errors method' do
|
540
|
-
it 'includes a generic error message for the named field' do
|
541
|
-
@form.errors.map(&:to_s).must_include('Email is invalid')
|
542
|
-
end
|
543
|
-
end
|
544
|
-
|
545
|
-
describe 'errors_on query method' do
|
546
|
-
it 'returns true when given the field name' do
|
547
|
-
@form.errors_on?(:email).must_equal(true)
|
548
|
-
end
|
549
|
-
end
|
550
|
-
end
|
551
|
-
|
552
|
-
describe 'FormWithCustomEmailValidation after parsing blank input' do
|
553
|
-
before do
|
554
|
-
@form = FormWithCustomEmailValidation.new
|
555
|
-
@form.parse('email=')
|
556
|
-
end
|
557
|
-
|
558
|
-
describe 'errors method' do
|
559
|
-
it 'will not include the custom validation error message' do
|
560
|
-
@form.errors.map(&:to_s).wont_include('Email is invalid')
|
561
|
-
end
|
562
|
-
end
|
563
|
-
end
|
564
|
-
|
565
|
-
class FormWithCustomPasswordConfirmationCheck < Formeze::Form
|
566
|
-
field :password
|
567
|
-
field :password_confirmation
|
568
|
-
|
569
|
-
validates :password_confirmation, :error => :does_not_match do
|
570
|
-
password_confirmation == password
|
571
|
-
end
|
572
|
-
end
|
573
|
-
|
574
|
-
describe 'FormWithCustomPasswordConfirmationCheck after parsing invalid input' do
|
575
|
-
before do
|
576
|
-
@form = FormWithCustomPasswordConfirmationCheck.new
|
577
|
-
@form.parse('password=foo&password_confirmation=bar')
|
578
|
-
end
|
579
|
-
|
580
|
-
describe 'valid query method' do
|
581
|
-
it 'returns false' do
|
582
|
-
@form.valid?.must_equal(false)
|
583
|
-
end
|
584
|
-
end
|
585
|
-
|
586
|
-
describe 'errors method' do
|
587
|
-
it 'includes a generic error message for the named field' do
|
588
|
-
@form.errors.map(&:to_s).must_include('Password confirmation is invalid')
|
589
|
-
end
|
590
|
-
end
|
591
|
-
|
592
|
-
describe 'errors_on query method' do
|
593
|
-
it 'returns true when given the field name' do
|
594
|
-
@form.errors_on?(:password_confirmation).must_equal(true)
|
595
|
-
end
|
596
|
-
end
|
597
|
-
end
|
598
|
-
|
599
|
-
class FormWithCustomMinimumSpendValidation < Formeze::Form
|
600
|
-
field :minimum_spend
|
601
|
-
|
602
|
-
field :fixed_discount, :required => false, :blank => nil
|
603
|
-
|
604
|
-
validates :minimum_spend, :when => :fixed_discount? do
|
605
|
-
minimum_spend.to_f > 0
|
606
|
-
end
|
607
|
-
|
608
|
-
def fixed_discount?
|
609
|
-
!fixed_discount.nil?
|
610
|
-
end
|
611
|
-
end
|
612
|
-
|
613
|
-
describe 'FormWithCustomMinimumSpendValidation after parsing valid input' do
|
614
|
-
before do
|
615
|
-
@form = FormWithCustomMinimumSpendValidation.new
|
616
|
-
@form.parse('minimum_spend=0.00&fixed_discount=')
|
617
|
-
end
|
618
|
-
|
619
|
-
describe 'valid query method' do
|
620
|
-
it 'returns true' do
|
621
|
-
@form.valid?.must_equal(true)
|
622
|
-
end
|
623
|
-
end
|
624
|
-
|
625
|
-
describe 'errors method' do
|
626
|
-
it 'returns an empty array' do
|
627
|
-
@form.errors.must_be_empty
|
628
|
-
end
|
629
|
-
end
|
630
|
-
|
631
|
-
describe 'errors_on query method' do
|
632
|
-
it 'returns false when given the field name' do
|
633
|
-
@form.errors_on?(:minimum_spend).must_equal(false)
|
634
|
-
end
|
635
|
-
end
|
636
|
-
end
|
637
|
-
|
638
|
-
describe 'FormWithCustomMinimumSpendValidation after parsing invalid input' do
|
639
|
-
before do
|
640
|
-
@form = FormWithCustomMinimumSpendValidation.new
|
641
|
-
@form.parse('minimum_spend=0.00&fixed_discount=10%')
|
642
|
-
end
|
643
|
-
|
644
|
-
describe 'valid query method' do
|
645
|
-
it 'returns false' do
|
646
|
-
@form.valid?.must_equal(false)
|
647
|
-
end
|
648
|
-
end
|
649
|
-
|
650
|
-
describe 'errors method' do
|
651
|
-
it 'includes a generic error message for the named field' do
|
652
|
-
@form.errors.map(&:to_s).must_include('Minimum spend is invalid')
|
653
|
-
end
|
654
|
-
end
|
655
|
-
|
656
|
-
describe 'errors_on query method' do
|
657
|
-
it 'returns true when given the field name' do
|
658
|
-
@form.errors_on?(:minimum_spend).must_equal(true)
|
659
|
-
end
|
660
|
-
end
|
661
|
-
end
|
662
|
-
|
663
|
-
class FormWithOptionalFieldAndCustomValidation < Formeze::Form
|
664
|
-
field :website, :required => false
|
665
|
-
|
666
|
-
validates :website do
|
667
|
-
website =~ /\./ && website !~ /\s/
|
668
|
-
end
|
669
|
-
end
|
670
|
-
|
671
|
-
describe 'FormWithOptionalFieldAndCustomValidation after parsing blank input' do
|
672
|
-
before do
|
673
|
-
@form = FormWithOptionalFieldAndCustomValidation.new
|
674
|
-
@form.parse('website=')
|
675
|
-
end
|
676
|
-
|
677
|
-
describe 'valid query method' do
|
678
|
-
it 'returns true' do
|
679
|
-
@form.valid?.must_equal(true)
|
680
|
-
end
|
681
|
-
end
|
682
|
-
|
683
|
-
describe 'errors method' do
|
684
|
-
it 'returns an empty array' do
|
685
|
-
@form.errors.must_be_empty
|
686
|
-
end
|
687
|
-
end
|
688
|
-
|
689
|
-
describe 'errors_on query method' do
|
690
|
-
it 'returns false when given the field name' do
|
691
|
-
@form.errors_on?(:website).must_equal(false)
|
692
|
-
end
|
693
|
-
end
|
694
|
-
end
|
695
|
-
|
696
|
-
class FormWithFileField < Formeze::Form
|
697
|
-
field :file, :maxsize => 42, :accept => 'text/plain'
|
698
|
-
end
|
699
|
-
|
700
|
-
describe 'FormWithFileField after parsing multipart input' do
|
701
|
-
before do
|
702
|
-
@form = FormWithFileField.new
|
703
|
-
|
704
|
-
body = <<-EOS.gsub(/\n/, "\r\n")
|
705
|
-
--AaB03x
|
706
|
-
Content-Disposition: form-data; name="file"; filename="example.txt"
|
707
|
-
Content-Type: text/plain
|
708
|
-
|
709
|
-
contents
|
710
|
-
--AaB03x--
|
711
|
-
EOS
|
712
|
-
|
713
|
-
request = Struct.new(:body, :env).new(StringIO.new(body), {
|
714
|
-
'REQUEST_METHOD' => 'POST',
|
715
|
-
'CONTENT_TYPE' => 'multipart/form-data; boundary=AaB03x',
|
716
|
-
'CONTENT_LENGTH' => body.bytesize
|
717
|
-
})
|
718
|
-
|
719
|
-
@form.parse(request)
|
720
|
-
end
|
721
|
-
|
722
|
-
describe 'file method' do
|
723
|
-
it 'returns the value of the field' do
|
724
|
-
@form.file.must_be_instance_of(StringIO)
|
725
|
-
@form.file.original_filename.must_equal('example.txt')
|
726
|
-
end
|
727
|
-
end
|
728
|
-
|
729
|
-
describe 'valid query method' do
|
730
|
-
it 'returns true' do
|
731
|
-
@form.valid?.must_equal(true)
|
732
|
-
end
|
733
|
-
end
|
734
|
-
|
735
|
-
describe 'errors query method' do
|
736
|
-
it 'returns false' do
|
737
|
-
@form.errors?.must_equal(false)
|
738
|
-
end
|
739
|
-
end
|
740
|
-
|
741
|
-
describe 'errors method' do
|
742
|
-
it 'returns an empty array' do
|
743
|
-
@form.errors.must_equal([])
|
744
|
-
end
|
745
|
-
end
|
746
|
-
|
747
|
-
describe 'errors_on query method' do
|
748
|
-
it 'returns false when given the file field name' do
|
749
|
-
@form.errors_on?(:file).must_equal(false)
|
750
|
-
end
|
751
|
-
end
|
752
|
-
|
753
|
-
describe 'errors_on method' do
|
754
|
-
it 'returns an empty array when given the file field name' do
|
755
|
-
@form.errors_on(:file).must_equal([])
|
756
|
-
end
|
757
|
-
end
|
758
|
-
end
|
759
|
-
|
760
|
-
describe 'FormWithFileField after parsing blank multipart input' do
|
761
|
-
before do
|
762
|
-
@form = FormWithFileField.new
|
763
|
-
|
764
|
-
body = <<-EOS.gsub(/\n/, "\r\n")
|
765
|
-
--AaB03x
|
766
|
-
Content-Disposition: form-data; name="file"; filename=""
|
767
|
-
Content-Type: application/octet-stream
|
768
|
-
|
769
|
-
|
770
|
-
--AaB03x--
|
771
|
-
EOS
|
772
|
-
|
773
|
-
request = Struct.new(:body, :env).new(StringIO.new(body), {
|
774
|
-
'REQUEST_METHOD' => 'POST',
|
775
|
-
'CONTENT_TYPE' => 'multipart/form-data; boundary=AaB03x',
|
776
|
-
'CONTENT_LENGTH' => body.bytesize
|
777
|
-
})
|
778
|
-
|
779
|
-
@form.parse(request)
|
780
|
-
end
|
781
|
-
|
782
|
-
describe 'errors query method' do
|
783
|
-
it 'returns true' do
|
784
|
-
@form.errors?.must_equal(true)
|
785
|
-
end
|
786
|
-
end
|
787
|
-
|
788
|
-
describe 'errors method' do
|
789
|
-
it 'returns an array containing a single error message' do
|
790
|
-
@form.errors.must_be_instance_of(Array)
|
791
|
-
@form.errors.length.must_equal(1)
|
792
|
-
@form.errors.first.to_s.must_equal('File is required')
|
793
|
-
end
|
794
|
-
end
|
795
|
-
|
796
|
-
describe 'errors_on query method' do
|
797
|
-
it 'returns true when given the file field name' do
|
798
|
-
@form.errors_on?(:file).must_equal(true)
|
799
|
-
end
|
800
|
-
end
|
801
|
-
|
802
|
-
describe 'errors_on method' do
|
803
|
-
it 'returns an array containing a single error message when given the file field name' do
|
804
|
-
errors = @form.errors_on(:file)
|
805
|
-
errors.must_be_instance_of(Array)
|
806
|
-
errors.length.must_equal(1)
|
807
|
-
errors.first.to_s.must_equal('File is required')
|
808
|
-
end
|
809
|
-
end
|
810
|
-
end
|
811
|
-
|
812
|
-
describe 'FormWithFileField after parsing multipart input with too much data' do
|
813
|
-
before do
|
814
|
-
@form = FormWithFileField.new
|
815
|
-
|
816
|
-
body = <<-EOS.gsub(/\n/, "\r\n")
|
817
|
-
--AaB03x
|
818
|
-
Content-Disposition: form-data; name="file"; filename="example.txt"
|
819
|
-
Content-Type: text/plain
|
820
|
-
|
821
|
-
The quick brown fox jumps over the lazy dog.
|
822
|
-
--AaB03x--
|
823
|
-
EOS
|
824
|
-
|
825
|
-
request = Struct.new(:body, :env).new(StringIO.new(body), {
|
826
|
-
'REQUEST_METHOD' => 'POST',
|
827
|
-
'CONTENT_TYPE' => 'multipart/form-data; boundary=AaB03x',
|
828
|
-
'CONTENT_LENGTH' => body.bytesize
|
829
|
-
})
|
830
|
-
|
831
|
-
@form.parse(request)
|
832
|
-
end
|
833
|
-
|
834
|
-
describe 'errors query method' do
|
835
|
-
it 'returns true' do
|
836
|
-
@form.errors?.must_equal(true)
|
837
|
-
end
|
838
|
-
end
|
839
|
-
|
840
|
-
describe 'errors method' do
|
841
|
-
it 'returns an array containing a single error message' do
|
842
|
-
@form.errors.must_be_instance_of(Array)
|
843
|
-
@form.errors.length.must_equal(1)
|
844
|
-
@form.errors.first.to_s.must_equal('File is too large')
|
845
|
-
end
|
846
|
-
end
|
847
|
-
|
848
|
-
describe 'errors_on query method' do
|
849
|
-
it 'returns true when given the file field name' do
|
850
|
-
@form.errors_on?(:file).must_equal(true)
|
851
|
-
end
|
852
|
-
end
|
853
|
-
|
854
|
-
describe 'errors_on method' do
|
855
|
-
it 'returns an array containing a single error message when given the file field name' do
|
856
|
-
errors = @form.errors_on(:file)
|
857
|
-
errors.must_be_instance_of(Array)
|
858
|
-
errors.length.must_equal(1)
|
859
|
-
errors.first.to_s.must_equal('File is too large')
|
860
|
-
end
|
861
|
-
end
|
862
|
-
end
|
863
|
-
|
864
|
-
describe 'FormWithFileField after parsing multipart input with an unacceptable content type' do
|
865
|
-
before do
|
866
|
-
@form = FormWithFileField.new
|
867
|
-
|
868
|
-
body = <<-EOS.gsub(/\n/, "\r\n")
|
869
|
-
--AaB03x
|
870
|
-
Content-Disposition: form-data; name="file"; filename="example.html"
|
871
|
-
Content-Type: text/html
|
872
|
-
|
873
|
-
<!DOCTYPE html>
|
874
|
-
--AaB03x--
|
875
|
-
EOS
|
876
|
-
|
877
|
-
request = Struct.new(:body, :env).new(StringIO.new(body), {
|
878
|
-
'REQUEST_METHOD' => 'POST',
|
879
|
-
'CONTENT_TYPE' => 'multipart/form-data; boundary=AaB03x',
|
880
|
-
'CONTENT_LENGTH' => body.bytesize
|
881
|
-
})
|
882
|
-
|
883
|
-
@form.parse(request)
|
884
|
-
end
|
885
|
-
|
886
|
-
describe 'errors query method' do
|
887
|
-
it 'returns true' do
|
888
|
-
@form.errors?.must_equal(true)
|
889
|
-
end
|
890
|
-
end
|
891
|
-
|
892
|
-
describe 'errors method' do
|
893
|
-
it 'returns an array containing a single error message' do
|
894
|
-
@form.errors.must_be_instance_of(Array)
|
895
|
-
@form.errors.length.must_equal(1)
|
896
|
-
@form.errors.first.to_s.must_equal('File is not an accepted file type')
|
897
|
-
end
|
898
|
-
end
|
899
|
-
|
900
|
-
describe 'errors_on query method' do
|
901
|
-
it 'returns true when given the file field name' do
|
902
|
-
@form.errors_on?(:file).must_equal(true)
|
903
|
-
end
|
904
|
-
end
|
905
|
-
|
906
|
-
describe 'errors_on method' do
|
907
|
-
it 'returns an array containing a single error message when given the file field name' do
|
908
|
-
errors = @form.errors_on(:file)
|
909
|
-
errors.must_be_instance_of(Array)
|
910
|
-
errors.length.must_equal(1)
|
911
|
-
errors.first.to_s.must_equal('File is not an accepted file type')
|
912
|
-
end
|
913
|
-
end
|
914
|
-
end
|
915
|
-
|
916
|
-
describe 'FormWithField on Rails' do
|
917
|
-
before do
|
918
|
-
@form = FormWithField.new
|
919
|
-
|
920
|
-
Object.const_set(:Rails, Object.new)
|
921
|
-
end
|
922
|
-
|
923
|
-
after do
|
924
|
-
Object.send(:remove_const, :Rails)
|
925
|
-
end
|
926
|
-
|
927
|
-
describe 'parse method' do
|
928
|
-
it 'silently ignores the utf8 and authenticity_token parameters' do
|
929
|
-
@form.parse('utf8=%E2%9C%93&authenticity_token=5RMc3sPZdR%2BZz4onNS8NfK&title=Test')
|
930
|
-
@form.wont_respond_to(:utf8)
|
931
|
-
@form.wont_respond_to(:authenticity_token)
|
932
|
-
@form.to_hash.must_equal({:title => 'Test'})
|
933
|
-
end
|
934
|
-
end
|
935
|
-
end
|
936
|
-
|
937
|
-
describe 'I18n integration' do
|
938
|
-
before do
|
939
|
-
I18n.backend = I18n::Backend::Simple.new
|
940
|
-
end
|
941
|
-
|
942
|
-
after do
|
943
|
-
I18n.backend = I18n::Backend::Simple.new
|
944
|
-
end
|
945
|
-
|
946
|
-
it 'provides i18n support for overriding the default error messages' do
|
947
|
-
I18n.backend.store_translations :en, {:formeze => {:errors => {:required => 'cannot be blank'}}}
|
948
|
-
|
949
|
-
form = FormWithField.new
|
950
|
-
form.parse('title=')
|
951
|
-
form.errors.first.to_s.must_equal('Title cannot be blank')
|
952
|
-
end
|
953
|
-
|
954
|
-
it 'provides i18n support for overriding the default custom validation error message' do
|
955
|
-
I18n.backend.store_translations :en, {:formeze => {:errors => {:invalid => 'is not valid'}}}
|
956
|
-
|
957
|
-
form = FormWithCustomEmailValidation.new
|
958
|
-
form.parse('email=alice')
|
959
|
-
form.errors.first.to_s.must_equal('Email is not valid')
|
960
|
-
end
|
961
|
-
|
962
|
-
it 'provides i18n support for specifying custom validation error messages' do
|
963
|
-
I18n.backend.store_translations :en, {:formeze => {:errors => {:does_not_match => 'does not match'}}}
|
964
|
-
|
965
|
-
form = FormWithCustomPasswordConfirmationCheck.new
|
966
|
-
form.parse('password=foo&password_confirmation=bar')
|
967
|
-
form.errors.first.to_s.must_equal('Password confirmation does not match')
|
968
|
-
end
|
969
|
-
|
970
|
-
it 'provides i18n support for specifying field labels globally' do
|
971
|
-
I18n.backend.store_translations :en, {:formeze => {:labels => {:title => 'TITLE'}}}
|
972
|
-
|
973
|
-
form = FormWithField.new
|
974
|
-
form.parse('title=')
|
975
|
-
form.errors.first.to_s.must_equal('TITLE is required')
|
976
|
-
end
|
977
|
-
end
|
978
|
-
|
979
|
-
class FormWithScrubbedFields < Formeze::Form
|
980
|
-
field :postcode, :scrub => [:strip, :squeeze, :upcase], :pattern => /\A[A-Z0-9]{2,4} [A-Z0-9]{3}\z/
|
981
|
-
field :bio, :scrub => [:strip, :squeeze_lines], :multiline => true
|
982
|
-
end
|
983
|
-
|
984
|
-
describe 'FormWithScrubbedFields' do
|
985
|
-
describe 'parse method' do
|
986
|
-
it 'applies the scrub methods to the input before validation' do
|
987
|
-
form = FormWithScrubbedFields.new
|
988
|
-
form.parse('postcode=++sw1a+++1aa&bio=My+name+is+Cookie+Monster.%0A%0A%0A%0AI+LOVE+COOKIES!!!!%0A%0A%0A%0A')
|
989
|
-
form.postcode.must_equal('SW1A 1AA')
|
990
|
-
form.bio.count("\n").must_equal(2)
|
991
|
-
form.valid?.must_equal(true)
|
992
|
-
end
|
993
|
-
end
|
994
|
-
end
|
995
|
-
|
996
|
-
describe 'Formeze' do
|
997
|
-
describe 'scrub module method' do
|
998
|
-
it 'applies the scrub methods to the given input' do
|
999
|
-
Formeze.scrub("word\n\n", [:strip, :upcase]).must_equal('WORD')
|
1000
|
-
end
|
1001
|
-
end
|
1002
|
-
end
|
1003
|
-
|
1004
|
-
class FormClassWithExplicitSetupCall
|
1005
|
-
Formeze.setup(self)
|
1006
|
-
end
|
1007
|
-
|
1008
|
-
describe 'FormClassWithExplicitSetupCall' do
|
1009
|
-
before do
|
1010
|
-
@form_class = FormClassWithExplicitSetupCall
|
1011
|
-
end
|
1012
|
-
|
1013
|
-
it 'includes the formeze class methods and instance methods' do
|
1014
|
-
@form_class.singleton_class.must_include(Formeze::ClassMethods)
|
1015
|
-
|
1016
|
-
@form_class.must_include(Formeze::InstanceMethods)
|
1017
|
-
end
|
1018
|
-
end
|