judge 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/README.md +273 -14
  2. data/app/assets/javascripts/judge.js +391 -0
  3. data/app/controllers/judge/validations_controller.rb +9 -0
  4. data/app/models/judge/validation.rb +53 -0
  5. data/config/routes.rb +3 -0
  6. data/lib/generators/judge/install/install_generator.rb +42 -0
  7. data/lib/judge.rb +13 -8
  8. data/lib/judge/config.rb +39 -0
  9. data/lib/judge/controller.rb +35 -0
  10. data/lib/judge/each_validator.rb +5 -4
  11. data/lib/judge/engine.rb +5 -0
  12. data/lib/judge/form_builder.rb +19 -24
  13. data/lib/judge/html.rb +5 -7
  14. data/lib/judge/message_collection.rb +2 -1
  15. data/lib/judge/message_config.rb +2 -1
  16. data/lib/judge/validator.rb +3 -1
  17. data/lib/judge/validator_collection.rb +1 -1
  18. data/lib/judge/version.rb +2 -2
  19. data/lib/tasks/judge_tasks.rake +4 -0
  20. data/{lib/generators/judge/templates → vendor/assets/javascripts}/json2.js +4 -5
  21. data/{lib/generators/judge/templates → vendor/assets/javascripts}/underscore.js +451 -285
  22. metadata +94 -87
  23. data/.gitignore +0 -9
  24. data/.travis.yml +0 -21
  25. data/Gemfile +0 -3
  26. data/Rakefile +0 -11
  27. data/judge.gemspec +0 -23
  28. data/lib/generators/judge/judge_generator.rb +0 -21
  29. data/lib/generators/judge/templates/judge.js +0 -330
  30. data/spec/each_validator_spec.rb +0 -17
  31. data/spec/form_builder_spec.rb +0 -68
  32. data/spec/html_spec.rb +0 -14
  33. data/spec/javascripts/JudgeSpec.js +0 -509
  34. data/spec/javascripts/fixtures/form.html +0 -538
  35. data/spec/javascripts/helpers/customMatchers.js +0 -20
  36. data/spec/javascripts/helpers/jasmine-jquery.js +0 -204
  37. data/spec/javascripts/helpers/jquery-1.5.1.min.js +0 -18
  38. data/spec/javascripts/helpers/json2.js +0 -487
  39. data/spec/javascripts/helpers/underscore.js +0 -1060
  40. data/spec/javascripts/support/jasmine.yml +0 -79
  41. data/spec/javascripts/support/jasmine_config.rb +0 -6
  42. data/spec/javascripts/support/jasmine_runner.rb +0 -21
  43. data/spec/javascripts/support/runner.js +0 -51
  44. data/spec/message_collection_spec.rb +0 -73
  45. data/spec/setup.rb +0 -75
  46. data/spec/support/factories.rb +0 -23
  47. data/spec/support/locale/en.yml +0 -18
  48. data/spec/support/setup.rb +0 -72
  49. data/spec/support/spec_helper.rb +0 -13
  50. data/spec/support/validators/city_validator.rb +0 -9
  51. data/spec/validator_collection_spec.rb +0 -21
  52. data/spec/validator_spec.rb +0 -33
@@ -1,17 +0,0 @@
1
- require "support/spec_helper"
2
-
3
- describe Judge::EachValidator do
4
-
5
- let(:amv) { User.validators_on(:city).first }
6
-
7
- specify "custom validators include Judge::EachValidator" do
8
- CityValidator.include?(Judge::EachValidator).should be_true
9
- end
10
-
11
- specify "#messages_to_lookup method should return array of messages" do
12
- amv.should respond_to :messages_to_lookup
13
- amv.messages_to_lookup.should be_an Array
14
- amv.messages_to_lookup.should include :not_valid_city
15
- end
16
-
17
- end
@@ -1,68 +0,0 @@
1
- require "support/spec_helper"
2
-
3
- describe Judge::FormBuilder do
4
-
5
- let(:builder) { Judge::FormBuilder.new(:user, FactoryGirl.build(:user), ActionView::Base.new, {}, nil) }
6
- let(:categories) do
7
- category = FactoryGirl.build(:category)
8
- sport = FactoryGirl.build(:sport)
9
- sport.disciplines << FactoryGirl.build_list(:discipline, 3)
10
- category.sports << sport
11
- [category]
12
- end
13
- let(:expected) do
14
- /data\-validate=\"\[.+\]\"/
15
- end
16
-
17
- specify "#text_field" do
18
- builder.text_field(:name, :validate => true).should match expected
19
- end
20
-
21
- specify "#text_area" do
22
- builder.text_area(:bio, :validate => true).should match expected
23
- end
24
-
25
- specify "#password_field" do
26
- builder.password_field(:password, :validate => true).should match expected
27
- end
28
-
29
- specify "#check_box" do
30
- builder.check_box(:accepted, :validate => true).should match expected
31
- end
32
-
33
- specify "#radio_button" do
34
- builder.radio_button(:gender, "female", :validate => true).should match expected
35
- end
36
-
37
- specify "#select" do
38
- builder.select(:country, [["US", "US"], ["GB", "GB"]], :validate => true).should match expected
39
- end
40
-
41
- specify "#collection_select" do
42
- cs = builder.collection_select(:team_id, FactoryGirl.create_list(:team, 5), :id, :name, :validate => true)
43
- cs.should match expected
44
- end
45
-
46
- specify "#grouped_collection_select" do
47
- gcs = builder.grouped_collection_select(:discipline_id, categories, :sports, :name, :id, :name, :validate => true)
48
- gcs.should match expected
49
- end
50
-
51
- specify "#date_select" do
52
- builder.date_select(:dob, :validate => true, :minute_step => 30).should match expected
53
- end
54
-
55
- specify "#datetime_select" do
56
- builder.datetime_select(:dob, :validate => true, :minute_step => 30).should match expected
57
- end
58
-
59
- specify "#time_select" do
60
- builder.time_select(:dob, :validate => true, :minute_step => 30).should match expected
61
- end
62
-
63
- specify "#time_zone_select" do
64
- tzs = builder.time_zone_select(:time_zone, ActiveSupport::TimeZone.us_zones, :include_blank => true, :validate => true)
65
- tzs.should match expected
66
- end
67
-
68
- end
@@ -1,14 +0,0 @@
1
- require "support/spec_helper"
2
-
3
- describe Judge::HTML do
4
-
5
- let(:object) { FactoryGirl.build(:user) }
6
- let(:method) { :name }
7
-
8
- specify "#attrs_for" do
9
- attrs = Judge::HTML.attrs_for(object, method)
10
- attrs.should be_a Hash
11
- attrs["data-validate"].should be_a String
12
- end
13
-
14
- end
@@ -1,509 +0,0 @@
1
- describe('judge', function() {
2
-
3
- beforeEach(function() {
4
- this.addMatchers(customMatchers);
5
- });
6
-
7
- describe('judge.validate', function() {
8
-
9
- beforeEach(function() {
10
- loadFixtures('spec/javascripts/fixtures/form.html');
11
- });
12
-
13
- it('validates a single element', function() {
14
- var elements = document.getElementById('foo_one'),
15
- results = judge.validate(elements);
16
- expect(results.length).toEqual(1);
17
- });
18
-
19
- it('validates a collection of elements', function() {
20
- var elements = document.querySelectorAll('input[type=radio]'),
21
- results = judge.validate(elements);
22
- expect(results.length).toEqual(1);
23
- });
24
-
25
- describe('callbacks', function() {
26
- it('calls callback correct number of times', function() {
27
- var elements = document.getElementsByTagName('textarea');
28
- callback = jasmine.createSpy(),
29
- length = elements.length;
30
- judge.validate(elements, callback);
31
- expect(callback.callCount).toBe(length);
32
- });
33
- });
34
-
35
- });
36
-
37
- describe('judge.Watcher', function() {
38
-
39
- var watcher;
40
-
41
- beforeEach(function() {
42
- loadFixtures('spec/javascripts/fixtures/form.html');
43
- watcher = new judge.Watcher(document.getElementById('foo_one'));
44
- });
45
-
46
- it('returns new instance of judge', function() {
47
- expect(watcher.constructor).toEqual(judge.Watcher);
48
- });
49
-
50
- it('associates with element', function() {
51
- expect(watcher.element).toEqual(document.getElementById('foo_one'));
52
- });
53
-
54
- it('holds validators', function() {
55
- expect(_(watcher.validators).isArray()).toEqual(true);
56
- expect(_(watcher.validators).isEmpty()).toEqual(false);
57
- });
58
-
59
- it('holds messages inside validators', function() {
60
- expect(_(watcher.validators).first().messages).toBeInstanceOf(Object);
61
- });
62
-
63
- it('has validation methods in prototype', function() {
64
- expect(watcher.validates()).not.toBeEmpty();
65
- expect(_(watcher.validates()).keys()).toContain('presence');
66
- });
67
-
68
- it('has custom validation methods when defined by user', function() {
69
- judge.customValidators.phatness = function() {};
70
- expect(_(watcher.validates()).keys()).toContain('phatness');
71
- });
72
-
73
- it('throws error if element has no data-validate attribute', function() {
74
- var input = document.createElement('input');
75
- input.type = 'text';
76
- expect(function() { new judge.Watcher(input); }).toThrow();
77
- });
78
-
79
- it('throws error if no element is passed', function() {
80
- expect(function() { new judge.Watcher(); }).toThrow();
81
- });
82
-
83
- });
84
-
85
- describe('judge.Watcher instance methods', function() {
86
-
87
- beforeEach(function() {
88
- loadFixtures('spec/javascripts/fixtures/form.html');
89
- });
90
-
91
- describe('validate method', function() {
92
-
93
- var watcher, result;
94
-
95
- beforeEach(function() {
96
- watcher = new judge.Watcher(document.getElementById('foo_one'));
97
- result = watcher.validate();
98
- });
99
-
100
- it('returns element', function() {
101
- expect(result.element).toBeInstanceOf(Object);
102
- });
103
-
104
- it('returns validity', function() {
105
- expect(_.isBoolean(result.valid)).toBe(true);
106
- });
107
-
108
- it('returns messages', function() {
109
- expect(result.messages).toBeInstanceOf(Array);
110
- });
111
-
112
- describe('callback', function() {
113
-
114
- var callback, args;
115
-
116
- beforeEach(function() {
117
- callback = jasmine.createSpy();
118
- watcher.validate(callback);
119
- args = callback.argsForCall[0];
120
- });
121
-
122
- it('is called when given', function() {
123
- expect(callback).toHaveBeenCalled();
124
- });
125
- it('receives correct args', function() {
126
- expect(_.isBoolean(args[0])).toBe(true);
127
- expect(_.isArray(args[1])).toBe(true);
128
- expect(_.isElement(args[2])).toBe(true);
129
- });
130
-
131
- });
132
-
133
- });
134
-
135
- describe('presence', function() {
136
-
137
- var watcher;
138
-
139
- beforeEach(function() {
140
- watcher = new judge.Watcher(document.getElementById('foo_one'));
141
- });
142
-
143
- it('invalidates empty input', function() {
144
- expect(watcher.validate().valid).toEqual(false);
145
- });
146
-
147
- it('validates non-empty input', function() {
148
- watcher.element.children[1].selected = true;
149
- expect(watcher.validate().valid).toEqual(true);
150
- });
151
-
152
- });
153
-
154
- describe('length', function() {
155
-
156
- var watcher;
157
-
158
- beforeEach(function() {
159
- watcher = new judge.Watcher(document.getElementById('foo_two_foobar'));
160
- });
161
-
162
- it('validates valid input', function() {
163
- watcher.element.value = 'abcdef';
164
- expect(watcher.validate().valid).toEqual(true);
165
- });
166
-
167
- it('validates allow_blank', function() {
168
- watcher.element.value = '';
169
- expect(watcher.validate().valid).toEqual(true);
170
- });
171
-
172
- it('invalidates when value is under minimum', function() {
173
- watcher.element.value = 'abc';
174
- expect(watcher.validate().valid).toEqual(false);
175
- });
176
-
177
- it('invalidates when value is over maximum', function() {
178
- watcher.element.value = 'abcdefghijkl';
179
- expect(watcher.validate().valid).toEqual(false);
180
- });
181
- });
182
-
183
- describe('exclusion', function() {
184
-
185
- var watcher;
186
-
187
- beforeEach(function() {
188
- watcher = new judge.Watcher(document.getElementById('foo_three'));
189
- });
190
-
191
- it('validates when value is not in array', function() {
192
- expect(watcher.validate().valid).toEqual(true);
193
- });
194
-
195
- it('invalidates when value is in array', function() {
196
- watcher.element.children[1].selected = true;
197
- expect(watcher.validate().valid).toEqual(false);
198
- });
199
-
200
- });
201
-
202
- describe('inclusion', function() {
203
-
204
- var watcher;
205
-
206
- beforeEach(function() {
207
- watcher = new judge.Watcher(document.getElementById('foo_three_inc'));
208
- });
209
-
210
- it('validates when value is in array', function() {
211
- watcher.element.children[1].selected = true;
212
- expect(watcher.validate().valid).toEqual(true);
213
- });
214
-
215
- it('invalidates when value is not in array', function() {
216
- expect(watcher.validate().valid).toEqual(false);
217
- });
218
-
219
- });
220
-
221
- describe('numericality', function() {
222
-
223
- var watcher, watcherEven, watcherGt, watcherLt;
224
-
225
- beforeEach(function() {
226
- watcher = new judge.Watcher(document.getElementById('foo_four'));
227
- watcherEven = new judge.Watcher(document.getElementById('foo_four_even'));
228
- watcherGt = new judge.Watcher(document.getElementById('foo_four_gt'));
229
- watcherLt = new judge.Watcher(document.getElementById('foo_four_lt'));
230
- });
231
-
232
- it('invalidates when value is not a number', function() {
233
- watcher.element.value = 'foo bar';
234
- expect(watcher.validate().valid).toEqual(false);
235
- });
236
-
237
- it('validates odd / invalidates not odd', function() {
238
- watcher.element.value = '2';
239
- expect(watcher.validate().valid).toEqual(false);
240
- watcher.element.value = '1';
241
- expect(watcher.validate().valid).toEqual(true);
242
- });
243
-
244
- it('validates even / invalidates not even', function() {
245
- watcherEven.element.value = '1';
246
- expect(watcherEven.validate().valid).toEqual(false);
247
- watcherEven.element.value = '2';
248
- expect(watcherEven.validate().valid).toEqual(true);
249
- });
250
-
251
- describe('integer', function() {
252
-
253
- it('validates int', function() {
254
- watcher.element.value = '1';
255
- expect(watcher.validate().valid).toEqual(true);
256
- });
257
-
258
- it('invalidates float', function() {
259
- watcher.element.value = '1.1';
260
- expect(watcher.validate().valid).toEqual(false);
261
- });
262
-
263
- });
264
-
265
- describe('greater than', function() {
266
-
267
- it('invalidates not greater than', function() {
268
- watcherGt.element.value = '6';
269
- expect(watcherGt.validate().valid).toEqual(false);
270
- watcherGt.element.value = '7';
271
- expect(watcherGt.validate().valid).toEqual(false);
272
- });
273
-
274
- it('validates greater than', function() {
275
- watcherGt.element.value = '8';
276
- expect(watcherGt.validate().valid).toEqual(true);
277
- });
278
-
279
- });
280
-
281
- describe('less than', function() {
282
-
283
- it('invalidates not less than', function() {
284
- watcherLt.element.value = '8';
285
- expect(watcherLt.validate().valid).toEqual(false);
286
- watcherLt.element.value = '7';
287
- expect(watcherLt.validate().valid).toEqual(false);
288
- });
289
-
290
- it('validates less than', function() {
291
- watcherLt.element.value = '6';
292
- expect(watcherLt.validate().valid).toEqual(true);
293
- });
294
- });
295
- });
296
-
297
- describe('format', function() {
298
-
299
- describe('with', function() {
300
-
301
- var watcher;
302
-
303
- beforeEach(function() {
304
- watcher = new judge.Watcher(document.getElementById('foo_five_wi'));
305
- });
306
-
307
- it('invalidates value matching with', function() {
308
- expect(watcher.validate().valid).toEqual(false);
309
- });
310
-
311
- it('invalidates value not matching with', function() {
312
- watcher.element.children[1].selected = true;
313
- expect(watcher.validate().valid).toEqual(true);
314
- });
315
-
316
- });
317
-
318
- describe('without', function() {
319
-
320
- var watcher;
321
-
322
- beforeEach(function() {
323
- watcher = new judge.Watcher(document.getElementById('foo_five_wo'));
324
- });
325
-
326
- it('validates value not matching with', function() {
327
- expect(watcher.validate().valid).toEqual(true);
328
- });
329
-
330
- it('invalidates value matching with', function() {
331
- watcher.element.children[1].selected = true;
332
- expect(watcher.validate().valid).toEqual(false);
333
- });
334
-
335
- });
336
-
337
- });
338
-
339
- describe('acceptance', function() {
340
-
341
- var watcher;
342
-
343
- beforeEach(function() {
344
- watcher = new judge.Watcher(document.getElementById('foo_six'));
345
- });
346
-
347
- it('validates when element is checked', function() {
348
- watcher.element.checked = true;
349
- expect(watcher.validate().valid).toEqual(true);
350
- });
351
-
352
- it('invalidates when element is not checked', function() {
353
- expect(watcher.validate().valid).toEqual(false);
354
- });
355
-
356
- });
357
-
358
- describe('confirmation', function() {
359
-
360
- var watcher, conf;
361
-
362
- beforeEach(function() {
363
- watcher = new judge.Watcher(document.getElementById('foo_seven'));
364
- conf = document.getElementById('foo_seven_confirmation');
365
- });
366
-
367
- it('validates when confirmed', function() {
368
- watcher.element.value = 'password';
369
- conf.value = 'password';
370
- expect(watcher.validate().valid).toEqual(true);
371
- });
372
-
373
- it('invalidates when not confirmed', function() {
374
- watcher.element.value = 'password';
375
- conf.value = 'wrongpassword';
376
- expect(watcher.validate().valid).toEqual(false);
377
- });
378
-
379
- });
380
-
381
- });
382
-
383
- describe('judge.store', function() {
384
-
385
- var element;
386
-
387
- beforeEach(function() {
388
- loadFixtures('spec/javascripts/fixtures/form.html');
389
- judge.store.clear();
390
- element = document.getElementById('foo_one');
391
- });
392
-
393
- describe('save / get', function() {
394
-
395
- it('saves Watcher against key', function() {
396
- judge.store.save('mykey', element);
397
- expect(_(judge.store.get('mykey')).first().constructor).toEqual(judge.Watcher);
398
- expect(_(judge.store.get('mykey')).first().element).toBe(element);
399
- });
400
-
401
- it('does not save Watcher if element has already been stored against same key', function() {
402
- judge.store.save('mykey', element);
403
- judge.store.save('mykey', element);
404
- expect(judge.store.get('mykey').length).toEqual(1);
405
- });
406
-
407
- it('does save Watcher again if key is different', function() {
408
- judge.store.save('mykey', element);
409
- judge.store.save('mykey2', element);
410
- expect(judge.store.get('mykey').length).toEqual(1);
411
- expect(judge.store.get('mykey2').length).toEqual(1);
412
- });
413
-
414
- });
415
-
416
- describe('getDOM', function() {
417
-
418
- it('returns DOM elements from stored Watchers', function() {
419
- judge.store.save('mykey', element);
420
- judge.store.save('mykey', document.getElementById('foo_two_foobar'));
421
- var storedElements = judge.store.getDOM('mykey');
422
- expect(storedElements.length).toEqual(2);
423
- expect(Object.prototype.toString.call(storedElements[0])).toEqual('[object HTMLSelectElement]');
424
- });
425
-
426
- it('returns store object with watchers converted to elements if no key given', function() {
427
- judge.store.save('mykey', element);
428
- judge.store.save('mykey2', document.getElementById('foo_two_foobar'));
429
- judge.store.save('mykey2', document.getElementById('foo_three'));
430
- var storedElements = judge.store.getDOM();
431
- expect(storedElements.mykey.length).toEqual(1);
432
- expect(storedElements.mykey2.length).toEqual(2);
433
- expect(Object.prototype.toString.call(storedElements.mykey[0])).toEqual('[object HTMLSelectElement]');
434
- });
435
-
436
- it('returns null if key not found', function() {
437
- expect(judge.store.getDOM('notakey')).toEqual(null);
438
- });
439
-
440
- });
441
-
442
- describe('validate', function() {
443
-
444
- it('validates all elements stored against key', function() {
445
- judge.store.save('mykey', element);
446
- var results = judge.store.validate('mykey');
447
- expect(_(results).first()).toBeInstanceOf(Object);
448
- expect(_(results).first().element).toEqual(element);
449
- });
450
-
451
- it('calls callback correct number of times', function() {
452
- judge.store.save('mykey', document.getElementsByTagName('textarea'));
453
- var callback = jasmine.createSpy();
454
- judge.store.validate('mykey', callback);
455
- expect(callback.callCount).toBe(4);
456
- });
457
-
458
- it('returns null if no elements found', function() {
459
- var results = judge.store.validate('mykey');
460
- expect(results).toBe(null);
461
- });
462
-
463
- it('returns null if key is not passed', function() {
464
- var results = judge.store.validate();
465
- expect(results).toBe(null);
466
- });
467
-
468
- });
469
-
470
- describe('remove', function() {
471
-
472
- it('removes Watcher from store', function() {
473
- judge.store.save('mykey', element);
474
- expect(_(judge.store.remove('mykey', element)).isUndefined()).toEqual(true);
475
- expect(judge.store.get('mykey')).toBe(null);
476
- });
477
-
478
- it('returns null if key not found', function() {
479
- judge.store.save('mykey', element);
480
- expect(judge.store.remove('notakey', element)).toEqual(null);
481
- });
482
-
483
- });
484
-
485
- describe('clear', function() {
486
-
487
- it('clears entire store if no key is passed', function() {
488
- judge.store.save('mykey', element);
489
- judge.store.clear();
490
- expect(judge.store.get()).toEqual({});
491
- });
492
-
493
- it('clears all Watchers against key', function() {
494
- judge.store.save('mykey', element);
495
- judge.store.save('mykey2', element);
496
- judge.store.clear('mykey');
497
- expect(judge.store.get('mykey')).toBe(null);
498
- expect(judge.store.get('mykey2').length).toEqual(1);
499
- });
500
-
501
- it('returns null if key not found', function() {
502
- expect(judge.store.clear('notakey')).toBe(null);
503
- });
504
-
505
- });
506
-
507
- });
508
-
509
- });