judge 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/.document +5 -0
  2. data/.travis.yml +18 -0
  3. data/Gemfile +12 -0
  4. data/Gemfile.lock +112 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +20 -0
  7. data/Rakefile +51 -0
  8. data/VERSION +1 -0
  9. data/judge.gemspec +155 -0
  10. data/lib/generators/judge/judge_generator.rb +21 -0
  11. data/lib/generators/judge/templates/json2.js +483 -0
  12. data/lib/generators/judge/templates/judge.js +295 -0
  13. data/lib/generators/judge/templates/underscore.js +840 -0
  14. data/lib/judge.rb +4 -0
  15. data/lib/judge/helpers.rb +31 -0
  16. data/lib/tasks/js_tests.rake +27 -0
  17. data/spec/javascripts/JudgeSpec.js +670 -0
  18. data/spec/javascripts/fixtures/form.html +50 -0
  19. data/spec/javascripts/helpers/customMatchers.js +20 -0
  20. data/spec/javascripts/helpers/jasmine-jquery.js +204 -0
  21. data/spec/javascripts/helpers/jquery-1.5.1.min.js +18 -0
  22. data/spec/javascripts/helpers/json2.js +482 -0
  23. data/spec/javascripts/helpers/underscore.js +824 -0
  24. data/spec/javascripts/support/jasmine.yml +79 -0
  25. data/spec/javascripts/support/jasmine_config.rb +6 -0
  26. data/spec/javascripts/support/jasmine_runner.rb +32 -0
  27. data/spec/javascripts/support/phantomRunner.js +28 -0
  28. data/test/dummy/Rakefile +7 -0
  29. data/test/dummy/app/controllers/application_controller.rb +3 -0
  30. data/test/dummy/app/controllers/foos_controller.rb +5 -0
  31. data/test/dummy/app/helpers/application_helper.rb +2 -0
  32. data/test/dummy/app/models/foo.rb +11 -0
  33. data/test/dummy/app/views/foos/new.html.erb +42 -0
  34. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  35. data/test/dummy/config.ru +4 -0
  36. data/test/dummy/config/application.rb +45 -0
  37. data/test/dummy/config/boot.rb +10 -0
  38. data/test/dummy/config/database.yml +22 -0
  39. data/test/dummy/config/environment.rb +5 -0
  40. data/test/dummy/config/environments/development.rb +26 -0
  41. data/test/dummy/config/environments/production.rb +49 -0
  42. data/test/dummy/config/environments/test.rb +35 -0
  43. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  44. data/test/dummy/config/initializers/inflections.rb +10 -0
  45. data/test/dummy/config/initializers/mime_types.rb +5 -0
  46. data/test/dummy/config/initializers/secret_token.rb +7 -0
  47. data/test/dummy/config/initializers/session_store.rb +8 -0
  48. data/test/dummy/config/locales/en.yml +5 -0
  49. data/test/dummy/config/routes.rb +3 -0
  50. data/test/dummy/db/development.sqlite3 +0 -0
  51. data/test/dummy/db/migrate/20110624115516_create_foos.rb +26 -0
  52. data/test/dummy/db/schema.rb +34 -0
  53. data/test/dummy/db/test.sqlite3 +0 -0
  54. data/test/dummy/log/development.log +59 -0
  55. data/test/dummy/log/production.log +0 -0
  56. data/test/dummy/log/server.log +0 -0
  57. data/test/dummy/public/404.html +26 -0
  58. data/test/dummy/public/422.html +26 -0
  59. data/test/dummy/public/500.html +26 -0
  60. data/test/dummy/public/favicon.ico +0 -0
  61. data/test/dummy/public/javascripts/application.js +2 -0
  62. data/test/dummy/public/javascripts/controls.js +965 -0
  63. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  64. data/test/dummy/public/javascripts/effects.js +1123 -0
  65. data/test/dummy/public/javascripts/prototype.js +6001 -0
  66. data/test/dummy/public/javascripts/rails.js +175 -0
  67. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  68. data/test/dummy/script/rails +6 -0
  69. data/test/judge_test.rb +73 -0
  70. data/test/test_helper.rb +23 -0
  71. metadata +275 -0
data/lib/judge.rb ADDED
@@ -0,0 +1,4 @@
1
+ require File.dirname(__FILE__) + '/judge/helpers'
2
+
3
+ ::ActionView::Helpers::FormBuilder.send(:include, Judge::FieldHelpers)
4
+ ::ActionView::Helpers::FormHelper.send(:include, Judge::FormHelpers)
@@ -0,0 +1,31 @@
1
+ module Judge
2
+
3
+ module FieldHelpers
4
+
5
+ include ActionView::Helpers::TagHelper
6
+
7
+ %w{text_field text_area}.each do |type|
8
+ helper = <<-END
9
+ def validated_#{type}(method, options = {})
10
+ validators = self.object.class.validators_on(method).collect{ |v| { :kind => v.kind.to_s, :options => v.options } }
11
+ options = { "data-validate" => validators.to_json }.merge(options)
12
+ @template.#{type}(self.object_name, method, options)
13
+ end
14
+ END
15
+ class_eval helper, __FILE__, __LINE__
16
+ end
17
+
18
+ end
19
+
20
+ module FormHelpers
21
+
22
+ def validated_form_for(record_or_name_or_array, *args, &proc)
23
+ options = args.extract_options!
24
+ options[:html] ||= {}
25
+ options[:html]["data-error-messages"] = I18n.t("errors.messages").to_json
26
+ form_for(record_or_name_or_array, *(args << options), &proc)
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,27 @@
1
+ namespace :jasmine do
2
+ task :require_phantom_js do
3
+ sh "which phantomjs" do |ok, res|
4
+ fail 'Cannot find phantomjs on $PATH' unless ok
5
+ end
6
+ end
7
+
8
+ desc "Run continuous integration tests headlessly with phantom.js"
9
+ task :phantom => ['jasmine:require', 'jasmine:require_phantom_js'] do
10
+ support_dir = File.expand_path('../../spec/javascripts/support', File.dirname(__FILE__))
11
+ config_overrides = File.join(support_dir, 'jasmine_config.rb')
12
+ require config_overrides if File.exists?(config_overrides)
13
+ phantom_js_runner = File.join(support_dir, 'phantomRunner.js')
14
+
15
+ config = Jasmine::Config.new
16
+
17
+ # start the Jasmine server and wait up to 10 seconds for it to be running:
18
+ config.start_jasmine_server
19
+
20
+ jasmine_url = "#{config.jasmine_host}:#{config.jasmine_server_port}"
21
+ puts "Running tests against #{jasmine_url}"
22
+ sh "phantomjs #{phantom_js_runner} #{jasmine_url}" do |ok, res|
23
+ fail "jasmine suite failed" unless ok
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,670 @@
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 e = document.getElementById('foo_one'),
15
+ v = judge.validate(e);
16
+ expect(v.length).toEqual(1);
17
+ });
18
+
19
+ it('validates a collection of elements', function() {
20
+ var e = document.querySelectorAll('.field input'),
21
+ v = judge.validate(e);
22
+ expect(v.length).toBeGreaterThan(1);
23
+ });
24
+
25
+ });
26
+
27
+ describe('judge.Watcher', function() {
28
+
29
+ var j;
30
+
31
+ beforeEach(function() {
32
+ loadFixtures('spec/javascripts/fixtures/form.html');
33
+ j = new judge.Watcher(document.getElementById('foo_one'));
34
+ });
35
+
36
+ it('returns new instance of judge', function() {
37
+ expect(typeof j).toEqual('object');
38
+ expect(j.constructor).toEqual(judge.Watcher);
39
+ });
40
+
41
+ it('associates with element', function() {
42
+ expect(j.element).toEqual(document.getElementById('foo_one'));
43
+ });
44
+
45
+ it('holds validators', function() {
46
+ expect(_(j.validators).isArray()).toEqual(true);
47
+ expect(_(j.validators).isEmpty()).toEqual(false);
48
+ });
49
+
50
+ it('holds default messages', function() {
51
+ expect(j.defaultMessages).toBeInstanceOf(Object);
52
+ });
53
+
54
+ it('has validation methods in prototype', function() {
55
+ expect(j.validates()).not.toBeEmpty();
56
+ expect(_(j.validates()).keys()).toContain('presence');
57
+ });
58
+
59
+ it('has custom validation methods when defined by user', function() {
60
+ judge.customValidators.phatness = function(options) { return { valid: true }; };
61
+ expect(_(j.validates()).keys()).toContain('phatness');
62
+ });
63
+
64
+ it('throws error if element has no data-validate attribute', function() {
65
+ var e = document.createElement('input');
66
+ e.type = 'text';
67
+ expect(function() { new judge.Watcher(e); }).toThrow();
68
+ });
69
+
70
+ it('throws error if element.form has no data-error-messages attribute', function() {
71
+ var e = document.createElement('input'),
72
+ f = document.createElement('form');
73
+ e.type = 'text';
74
+ f.appendChild(e);
75
+ expect(function() { new judge.Watcher(e); }).toThrow();
76
+ });
77
+
78
+ it('throws error if no element is passed', function() {
79
+ expect(function() { new judge.Watcher(); }).toThrow();
80
+ });
81
+
82
+ it('throws error if element is not validatable', function() {
83
+ var e = document.createElement('p');
84
+ expect(function() { new judge.Watcher(e); }).toThrow();
85
+ });
86
+
87
+ });
88
+
89
+ describe('judge.store', function() {
90
+
91
+ var e;
92
+
93
+ beforeEach(function() {
94
+ loadFixtures('spec/javascripts/fixtures/form.html');
95
+ judge.store.clear();
96
+ e = document.getElementById('foo_one');
97
+ });
98
+
99
+ describe('save / get', function() {
100
+
101
+ it('saves Watcher against key', function() {
102
+ judge.store.save('mykey', e);
103
+ expect(_(judge.store.get('mykey')).first().constructor).toEqual(judge.Watcher);
104
+ expect(_(judge.store.get('mykey')).first().element).toBe(e);
105
+ });
106
+
107
+ it('does not save Watcher if element has already been stored against same key', function() {
108
+ judge.store.save('mykey', e);
109
+ judge.store.save('mykey', e);
110
+ expect(judge.store.get('mykey').length).toEqual(1);
111
+ });
112
+
113
+ it('does save Watcher again if key is different', function() {
114
+ judge.store.save('mykey', e);
115
+ judge.store.save('mykey2', e);
116
+ expect(judge.store.get('mykey').length).toEqual(1);
117
+ expect(judge.store.get('mykey2').length).toEqual(1);
118
+ });
119
+
120
+ });
121
+
122
+ describe('getDOM', function() {
123
+
124
+ it('returns DOM elements from stored Watchers', function() {
125
+ judge.store.save('mykey', e);
126
+ judge.store.save('mykey', document.getElementById('foo_two'));
127
+ var d = judge.store.getDOM('mykey');
128
+ expect(d.length).toEqual(2);
129
+ expect(Object.prototype.toString.call(d[0])).toEqual('[object HTMLInputElement]');
130
+ });
131
+
132
+ it('returns store object with watchers converted to elements if no key given', function() {
133
+ judge.store.save('mykey', e);
134
+ judge.store.save('mykey2', document.getElementById('foo_two'));
135
+ judge.store.save('mykey2', document.getElementById('foo_three'));
136
+ var d = judge.store.getDOM();
137
+ expect(d.mykey.length).toEqual(1);
138
+ expect(d.mykey2.length).toEqual(2);
139
+ expect(Object.prototype.toString.call(d.mykey[0])).toEqual('[object HTMLInputElement]');
140
+ });
141
+
142
+ it('returns null if key not found', function() {
143
+ expect(judge.store.getDOM('notakey')).toEqual(null);
144
+ });
145
+
146
+ });
147
+
148
+ describe('remove', function() {
149
+
150
+ it('removes Watcher from store', function() {
151
+ judge.store.save('mykey', e);
152
+ expect(judge.store.remove('mykey', e)).not.toEqual(null);
153
+ expect(judge.store.get('mykey').length).toEqual(0);
154
+ });
155
+
156
+ it('returns null if key not found', function() {
157
+ judge.store.save('mykey', e);
158
+ expect(judge.store.remove('notakey', e)).toEqual(null);
159
+ });
160
+
161
+ });
162
+
163
+ describe('clear', function() {
164
+
165
+ it('clears entire store if no key is passed', function() {
166
+ judge.store.save('mykey', e);
167
+ judge.store.clear();
168
+ expect(judge.store.get()).toEqual({});
169
+ });
170
+
171
+ it('clears all Watchers against key', function() {
172
+ judge.store.save('mykey', e);
173
+ judge.store.save('mykey2', e);
174
+ judge.store.clear('mykey');
175
+ expect(judge.store.get('mykey')).toEqual([]);
176
+ expect(judge.store.get('mykey2').length).toEqual(1);
177
+ });
178
+
179
+ it('returns null if key not found', function() {
180
+ expect(judge.store.clear('notakey')).toEqual(null);
181
+ });
182
+
183
+ });
184
+
185
+ });
186
+
187
+ describe('judge.Watcher instance methods', function() {
188
+
189
+ beforeEach(function() {
190
+ loadFixtures('spec/javascripts/fixtures/form.html');
191
+ });
192
+
193
+ describe('validate method', function() {
194
+
195
+ var j, r;
196
+
197
+ beforeEach(function() {
198
+ j = new judge.Watcher(document.getElementById('foo_one'));
199
+ r = j.validate();
200
+ });
201
+
202
+ it('returns element', function() {
203
+ expect(r.element).toBeInstanceOf(Object);
204
+ });
205
+
206
+ it('returns validity', function() {
207
+ expect(typeof r.valid).toEqual('boolean');
208
+ });
209
+
210
+ it('returns messages', function() {
211
+ expect(r.messages).toBeInstanceOf(Array);
212
+ });
213
+
214
+ });
215
+
216
+ describe('presence', function() {
217
+
218
+ var j;
219
+
220
+ beforeEach(function() {
221
+ j = new judge.Watcher(document.getElementById('foo_one'));
222
+ });
223
+
224
+ it('invalidates empty input', function() {
225
+ expect(j.validate().valid).toEqual(false);
226
+ });
227
+
228
+ it('returns custom message when present', function() {
229
+ _(j.validators).first().options.message = 'hello';
230
+ expect(j.validate().messages).toContain('hello');
231
+ });
232
+
233
+ it('returns default message', function() {
234
+ expect(j.validate().messages).toContain(j.defaultMessages.blank);
235
+ });
236
+
237
+ it('validates non-empty input', function() {
238
+ j.element.value = 'abcde';
239
+ expect(j.validate().valid).toEqual(true);
240
+ });
241
+
242
+ });
243
+
244
+ describe('length', function() {
245
+
246
+ var j, jIs;
247
+
248
+ beforeEach(function() {
249
+ j = new judge.Watcher(document.getElementById('foo_two'));
250
+ jIs = new judge.Watcher(document.getElementById('foo_two_is'));
251
+ });
252
+
253
+ it('validates valid input', function() {
254
+ j.element.value = 'abcdef';
255
+ expect(j.validate().valid).toEqual(true);
256
+ });
257
+
258
+ it('validates allow_blank', function() {
259
+ j.element.value = '';
260
+ expect(j.validate().valid).toEqual(true);
261
+ });
262
+
263
+ it('returns custom message when present', function() {
264
+ j.element.value = 'abc';
265
+ _(j.validators).first().options.too_short = 'oh dear';
266
+ expect(j.validate().messages).toContain('oh dear');
267
+ });
268
+
269
+ it('returns default message', function() {
270
+ j.element.value = 'abc';
271
+ expect(j.validate().messages).toContain(judge.utils.countMsg(j.defaultMessages.too_short, 5));
272
+ });
273
+
274
+ it('invalidates when value is under minimum', function() {
275
+ j.element.value = 'abc';
276
+ expect(j.validate().valid).toEqual(false);
277
+ });
278
+
279
+ it('invalidates when value is over maximum', function() {
280
+ j.element.value = 'abcdefghijkl';
281
+ expect(j.validate().valid).toEqual(false);
282
+ });
283
+
284
+ it('invalidates when value is not equal to is', function() {
285
+ jIs.element.value = 'abc';
286
+ expect(jIs.validate().valid).toEqual(false);
287
+ });
288
+ });
289
+
290
+ describe('exclusion', function() {
291
+
292
+ var j;
293
+
294
+ beforeEach(function() {
295
+ j = new judge.Watcher(document.getElementById('foo_three'));
296
+ });
297
+
298
+ it('validates when value is not in array', function() {
299
+ j.element.value = 'abc';
300
+ expect(j.validate().valid).toEqual(true);
301
+ });
302
+
303
+ it('invalidates when value is in array', function() {
304
+ j.element.value = 'foo';
305
+ expect(j.validate().valid).toEqual(false);
306
+ });
307
+
308
+ it('returns default message', function() {
309
+ j.element.value = 'foo';
310
+ expect(j.validate().messages).toContain(j.defaultMessages.exclusion);
311
+ });
312
+
313
+ it('returns default message', function() {
314
+ _(j.validators).first().options.message = 'restricted';
315
+ j.element.value = 'foo';
316
+ expect(j.validate().messages).toContain('restricted');
317
+ });
318
+
319
+ });
320
+
321
+ describe('inclusion', function() {
322
+
323
+ var j;
324
+
325
+ beforeEach(function() {
326
+ j = new judge.Watcher(document.getElementById('foo_three_inc'));
327
+ });
328
+
329
+ it('validates when value is in array', function() {
330
+ j.element.value = '3';
331
+ expect(j.validate().valid).toEqual(true);
332
+ });
333
+
334
+ it('invalidates when value is not in array', function() {
335
+ j.element.value = '10';
336
+ expect(j.validate().valid).toEqual(false);
337
+ });
338
+
339
+ it('returns default message', function() {
340
+ j.element.value = '10';
341
+ expect(j.validate().messages).toContain(j.defaultMessages.inclusion);
342
+ });
343
+
344
+ it('returns default message', function() {
345
+ _(j.validators).first().options.message = 'must be one of defined values';
346
+ j.element.value = 'foo';
347
+ expect(j.validate().messages).toContain('must be one of defined values');
348
+ });
349
+
350
+ });
351
+
352
+ describe('numericality', function() {
353
+
354
+ var j, jEven, jGt, jLt;
355
+
356
+ beforeEach(function() {
357
+ j = new judge.Watcher(document.getElementById('foo_four'));
358
+ jEven = new judge.Watcher(document.getElementById('foo_four_even'));
359
+ jGt = new judge.Watcher(document.getElementById('foo_four_gt'));
360
+ jLt = new judge.Watcher(document.getElementById('foo_four_lt'));
361
+ });
362
+
363
+ it('invalidates when value is not a number', function() {
364
+ j.element.value = 'foo bar';
365
+ expect(j.validate().valid).toEqual(false);
366
+ expect(j.validate().messages).toContain(j.defaultMessages.not_a_number);
367
+ });
368
+
369
+ it('validates odd / invalidates not odd', function() {
370
+ j.element.value = '2';
371
+ expect(j.validate().valid).toEqual(false);
372
+ expect(j.validate().messages).toContain(j.defaultMessages.odd);
373
+ j.element.value = '1';
374
+ expect(j.validate().valid).toEqual(true);
375
+ });
376
+
377
+ it('validates even / invalidates not even', function() {
378
+ jEven.element.value = '1';
379
+ expect(jEven.validate().valid).toEqual(false);
380
+ expect(jEven.validate().messages).toContain(jEven.defaultMessages.even);
381
+ jEven.element.value = '2';
382
+ expect(jEven.validate().valid).toEqual(true);
383
+ });
384
+
385
+ describe('integer', function() {
386
+
387
+ it('validates int', function() {
388
+ j.element.value = '1';
389
+ expect(j.validate().valid).toEqual(true);
390
+ });
391
+
392
+ it('invalidates float', function() {
393
+ j.element.value = '1.1';
394
+ expect(j.validate().valid).toEqual(false);
395
+ expect(j.validate().messages).toContain(j.defaultMessages.not_an_integer);
396
+ });
397
+
398
+ });
399
+
400
+ describe('greater than', function() {
401
+
402
+ it('invalidates not greater than', function() {
403
+ jGt.element.value = '6';
404
+ expect(jGt.validate().valid).toEqual(false);
405
+ expect(jGt.validate().messages).toContain(judge.utils.countMsg(jGt.defaultMessages.greater_than, 7));
406
+ jGt.element.value = '7';
407
+ expect(jGt.validate().valid).toEqual(false);
408
+ expect(jGt.validate().messages).toContain(judge.utils.countMsg(jGt.defaultMessages.greater_than, 7));
409
+ });
410
+
411
+ it('validates greater than', function() {
412
+ jGt.element.value = '8';
413
+ expect(jGt.validate().valid).toEqual(true);
414
+ });
415
+
416
+ });
417
+
418
+ describe('less than', function() {
419
+
420
+ it('invalidates not less than', function() {
421
+ jLt.element.value = '8';
422
+ expect(jLt.validate().valid).toEqual(false);
423
+ jLt.element.value = '7';
424
+ expect(jLt.validate().valid).toEqual(false);
425
+ });
426
+
427
+ it('validates less than', function() {
428
+ jLt.element.value = '6';
429
+ expect(jLt.validate().valid).toEqual(true);
430
+ });
431
+
432
+ });
433
+
434
+ it('validates equal to', function() {
435
+ jLt.element.value = '5';
436
+ expect(jLt.validate().valid).toEqual(false);
437
+ jLt.element.value = '6';
438
+ expect(jLt.validate().valid).toEqual(true);
439
+ });
440
+
441
+ it('validates less than or equal to', function() {
442
+ j.element.value = '5';
443
+ expect(j.validate().valid).toEqual(true);
444
+ j.element.value = '7';
445
+ expect(j.validate().valid).toEqual(true);
446
+ j.element.value = '9';
447
+ expect(j.validate().valid).toEqual(false);
448
+ });
449
+
450
+ it('validates greater than or equal to', function() {
451
+ jEven.element.value = '20';
452
+ expect(jEven.validate().valid).toEqual(true);
453
+ jEven.element.value = '2';
454
+ expect(jEven.validate().valid).toEqual(true);
455
+ jEven.element.value = '1';
456
+ expect(jEven.validate().valid).toEqual(false);
457
+ });
458
+
459
+ });
460
+
461
+ describe('format', function() {
462
+
463
+ describe('with', function() {
464
+
465
+ var j;
466
+
467
+ beforeEach(function() {
468
+ j = new judge.Watcher(document.getElementById('foo_five'));
469
+ });
470
+
471
+ it('validates value matching with', function() {
472
+ j.element.value = 'ABCabc123';
473
+ expect(j.validate().valid).toEqual(true);
474
+ });
475
+
476
+ it('invalidates value not matching with', function() {
477
+ j.element.value = '123';
478
+ expect(j.validate().valid).toEqual(false);
479
+ expect(j.validate().messages).toContain(j.defaultMessages.invalid);
480
+ });
481
+
482
+ });
483
+
484
+ describe('without', function() {
485
+
486
+ var j;
487
+
488
+ beforeEach(function() {
489
+ j = new judge.Watcher(document.getElementById('foo_five_wo'));
490
+ });
491
+
492
+ it('validates value matching with', function() {
493
+ j.element.value = '12345';
494
+ expect(j.validate().valid).toEqual(true);
495
+ });
496
+
497
+ it('invalidates value not matching with', function() {
498
+ j.element.value = 'AbC123';
499
+ expect(j.validate().valid).toEqual(false);
500
+ expect(j.validate().messages).toContain(j.defaultMessages.invalid);
501
+ });
502
+
503
+ });
504
+
505
+ });
506
+
507
+ });
508
+
509
+ describe('utils', function() {
510
+
511
+ describe('isValidatable', function() {
512
+
513
+ it('returns true if judge can validate object', function() {
514
+ var i = document.createElement('input'),
515
+ s = document.createElement('select'),
516
+ t = document.createElement('textarea');
517
+ expect(judge.utils.isValidatable(i)).toEqual(true);
518
+ expect(judge.utils.isValidatable(s)).toEqual(true);
519
+ expect(judge.utils.isValidatable(t)).toEqual(true);
520
+ });
521
+
522
+ it('returns false otherwise', function() {
523
+ var p = document.createElement('p');
524
+ expect(judge.utils.isValidatable(p)).toEqual(false);
525
+ });
526
+
527
+ });
528
+
529
+ describe('isCollection', function() {
530
+
531
+ beforeEach(function() {
532
+ loadFixtures('spec/javascripts/fixtures/form.html');
533
+ });
534
+
535
+ it('returns true if judge can treat object as collection', function() {
536
+ var a = [],
537
+ n = document.getElementsByTagName('input');
538
+ expect(judge.utils.isCollection(a)).toEqual(true);
539
+ expect(judge.utils.isCollection(n)).toEqual(true);
540
+ });
541
+
542
+ it('returns false otherwise', function() {
543
+ var o = { a:1, b:2 };
544
+ expect(judge.utils.isCollection(o)).toEqual(false);
545
+ });
546
+
547
+ });
548
+
549
+ describe('getObjectString', function() {
550
+
551
+ it('returns type as represented in Object.prototype.toString', function() {
552
+ var i = document.createElement('input'),
553
+ s = document.createElement('select');
554
+ expect(judge.utils.getObjectString(i)).toEqual('HTMLInputElement');
555
+ expect(judge.utils.getObjectString(s)).toEqual('HTMLSelectElement');
556
+ });
557
+
558
+ });
559
+
560
+ describe('countMsg', function() {
561
+
562
+ it('subs string', function() {
563
+ expect(judge.utils.countMsg('should be less than %{count}', 5)).toEqual('should be less than 5');
564
+ });
565
+
566
+ });
567
+
568
+ describe('isInt', function() {
569
+
570
+ it('returns true when int', function() {
571
+ expect(judge.utils.isInt(1)).toEqual(true);
572
+ expect(judge.utils.isInt(1.)).toEqual(true);
573
+ expect(judge.utils.isInt(1.0)).toEqual(true);
574
+ expect(judge.utils.isInt(0)).toEqual(true);
575
+ expect(judge.utils.isInt(-1)).toEqual(true);
576
+ });
577
+
578
+ it('returns false when not int', function() {
579
+ expect(judge.utils.isInt(1.1)).toEqual(false);
580
+ expect(judge.utils.isInt(-1.1)).toEqual(false);
581
+ });
582
+
583
+ });
584
+
585
+ describe('isFloat', function() {
586
+
587
+ it('returns true when float', function() {
588
+ expect(judge.utils.isFloat(1.1)).toEqual(true);
589
+ expect(judge.utils.isFloat(-1.1)).toEqual(true);
590
+ });
591
+
592
+ it('returns false when not float', function() {
593
+ expect(judge.utils.isFloat(1)).toEqual(false);
594
+ expect(judge.utils.isFloat(1.)).toEqual(false);
595
+ expect(judge.utils.isFloat(1.0)).toEqual(false);
596
+ expect(judge.utils.isFloat(0)).toEqual(false);
597
+ expect(judge.utils.isFloat(-1)).toEqual(false);
598
+ });
599
+
600
+ });
601
+
602
+ describe('isEven', function() {
603
+
604
+ it('returns true when even', function() {
605
+ expect(judge.utils.isEven(2)).toEqual(true);
606
+ expect(judge.utils.isEven(0)).toEqual(true);
607
+ expect(judge.utils.isEven(-2)).toEqual(true);
608
+ });
609
+
610
+ it('returns false when odd', function() {
611
+ expect(judge.utils.isEven(1)).toEqual(false);
612
+ expect(judge.utils.isEven(-1)).toEqual(false);
613
+ });
614
+
615
+ });
616
+
617
+ describe('isOdd', function() {
618
+
619
+ it('returns true when odd', function() {
620
+ expect(judge.utils.isOdd(1)).toEqual(true);
621
+ expect(judge.utils.isOdd(-1)).toEqual(true);
622
+ });
623
+
624
+ it('returns false when even', function() {
625
+ expect(judge.utils.isOdd(2)).toEqual(false);
626
+ expect(judge.utils.isOdd(0)).toEqual(false);
627
+ expect(judge.utils.isOdd(-2)).toEqual(false);
628
+ });
629
+
630
+ });
631
+
632
+ describe('operate', function() {
633
+
634
+ it('evaluates and returns true or false', function() {
635
+ expect(judge.utils.operate(1, '<', 4)).toEqual(true);
636
+ expect(judge.utils.operate(1, '==', 1)).toEqual(true);
637
+ expect(judge.utils.operate(1, '>=', 4)).toEqual(false);
638
+ });
639
+
640
+ });
641
+
642
+ describe('convertRegExp', function() {
643
+
644
+ it('converts string format options-first ruby regexp into RegExp object', function() {
645
+ var re = judge.utils.convertRegExp('(?mix:[A-Z0-9])');
646
+ expect(re).toBeInstanceOf(RegExp);
647
+ expect(re.source).toEqual('[A-Z0-9]');
648
+ expect(re.multiline).toEqual(true);
649
+ expect(re.global).toEqual(false);
650
+ });
651
+
652
+ });
653
+
654
+ describe('convertFlags', function() {
655
+
656
+ it('returns m if present in options string without negation', function() {
657
+ expect(judge.utils.convertFlags('imx')).toEqual('m');
658
+ });
659
+
660
+ it('returns empty string otherwise', function() {
661
+ expect(judge.utils.convertFlags('-imx')).toEqual('');
662
+ expect(judge.utils.convertFlags('ix')).toEqual('');
663
+ expect(judge.utils.convertFlags('-m')).toEqual('');
664
+ });
665
+
666
+ });
667
+
668
+ });
669
+
670
+ });