judge 1.5.0 → 2.0.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.
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
- });