nimboids-client_side_validations 3.0.3

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 (101) hide show
  1. data/client_side_validations.gemspec +45 -0
  2. data/javascript/rails.validations.js +393 -0
  3. data/lib/client_side_validations.rb +8 -0
  4. data/lib/client_side_validations/action_view.rb +13 -0
  5. data/lib/client_side_validations/action_view/form_builder.rb +64 -0
  6. data/lib/client_side_validations/action_view/form_helper.rb +69 -0
  7. data/lib/client_side_validations/action_view/form_tag_helper.rb +12 -0
  8. data/lib/client_side_validations/active_model.rb +52 -0
  9. data/lib/client_side_validations/active_model/acceptance.rb +10 -0
  10. data/lib/client_side_validations/active_model/exclusion.rb +15 -0
  11. data/lib/client_side_validations/active_model/format.rb +10 -0
  12. data/lib/client_side_validations/active_model/inclusion.rb +15 -0
  13. data/lib/client_side_validations/active_model/length.rb +22 -0
  14. data/lib/client_side_validations/active_model/numericality.rb +26 -0
  15. data/lib/client_side_validations/active_model/presence.rb +10 -0
  16. data/lib/client_side_validations/active_record.rb +11 -0
  17. data/lib/client_side_validations/active_record/middleware.rb +25 -0
  18. data/lib/client_side_validations/active_record/uniqueness.rb +26 -0
  19. data/lib/client_side_validations/core_ext.rb +3 -0
  20. data/lib/client_side_validations/core_ext/range.rb +10 -0
  21. data/lib/client_side_validations/core_ext/regexp.rb +14 -0
  22. data/lib/client_side_validations/formtastic.rb +21 -0
  23. data/lib/client_side_validations/middleware.rb +83 -0
  24. data/lib/client_side_validations/mongoid.rb +9 -0
  25. data/lib/client_side_validations/mongoid/middleware.rb +20 -0
  26. data/lib/client_side_validations/mongoid/uniqueness.rb +26 -0
  27. data/lib/client_side_validations/simple_form.rb +24 -0
  28. data/lib/client_side_validations/version.rb +3 -0
  29. data/lib/generators/client_side_validations/install_generator.rb +22 -0
  30. data/lib/generators/templates/README +7 -0
  31. data/lib/generators/templates/client_side_validations.rb +14 -0
  32. data/test/action_view/cases/helper.rb +152 -0
  33. data/test/action_view/cases/test_helpers.rb +237 -0
  34. data/test/action_view/cases/test_legacy_helpers.rb +150 -0
  35. data/test/action_view/models.rb +3 -0
  36. data/test/action_view/models/comment.rb +35 -0
  37. data/test/action_view/models/post.rb +35 -0
  38. data/test/active_model/cases/helper.rb +4 -0
  39. data/test/active_model/cases/test_acceptance_validator.rb +16 -0
  40. data/test/active_model/cases/test_base.rb +11 -0
  41. data/test/active_model/cases/test_confirmation_validator.rb +16 -0
  42. data/test/active_model/cases/test_exclusion_validator.rb +20 -0
  43. data/test/active_model/cases/test_format_validator.rb +21 -0
  44. data/test/active_model/cases/test_inclusion_validator.rb +21 -0
  45. data/test/active_model/cases/test_length_validator.rb +61 -0
  46. data/test/active_model/cases/test_numericality_validator.rb +46 -0
  47. data/test/active_model/cases/test_presence_validator.rb +16 -0
  48. data/test/active_model/cases/test_validations.rb +151 -0
  49. data/test/active_model/models/person.rb +17 -0
  50. data/test/active_record/cases/helper.rb +12 -0
  51. data/test/active_record/cases/test_base.rb +11 -0
  52. data/test/active_record/cases/test_middleware.rb +150 -0
  53. data/test/active_record/cases/test_uniqueness_validator.rb +45 -0
  54. data/test/active_record/models/guid.rb +7 -0
  55. data/test/active_record/models/user.rb +10 -0
  56. data/test/base_helper.rb +6 -0
  57. data/test/core_ext/cases/test_core_ext.rb +45 -0
  58. data/test/formtastic/cases/helper.rb +2 -0
  59. data/test/formtastic/cases/test_form_builder.rb +11 -0
  60. data/test/formtastic/cases/test_form_helper.rb +22 -0
  61. data/test/generators/cases/test_install_generator.rb +15 -0
  62. data/test/javascript/config.ru +3 -0
  63. data/test/javascript/public/test/callbacks/elementAfter.js +54 -0
  64. data/test/javascript/public/test/callbacks/elementBefore.js +54 -0
  65. data/test/javascript/public/test/callbacks/elementFail.js +70 -0
  66. data/test/javascript/public/test/callbacks/elementPass.js +70 -0
  67. data/test/javascript/public/test/callbacks/formAfter.js +45 -0
  68. data/test/javascript/public/test/callbacks/formBefore.js +45 -0
  69. data/test/javascript/public/test/callbacks/formFail.js +51 -0
  70. data/test/javascript/public/test/callbacks/formPass.js +50 -0
  71. data/test/javascript/public/test/form_builders/validateForm.js +66 -0
  72. data/test/javascript/public/test/form_builders/validateFormtastic.js +54 -0
  73. data/test/javascript/public/test/form_builders/validateSimpleForm.js +57 -0
  74. data/test/javascript/public/test/settings.js +15 -0
  75. data/test/javascript/public/test/validateElement.js +144 -0
  76. data/test/javascript/public/test/validators/acceptance.js +42 -0
  77. data/test/javascript/public/test/validators/confirmation.js +25 -0
  78. data/test/javascript/public/test/validators/exclusion.js +41 -0
  79. data/test/javascript/public/test/validators/format.js +27 -0
  80. data/test/javascript/public/test/validators/inclusion.js +42 -0
  81. data/test/javascript/public/test/validators/length.js +70 -0
  82. data/test/javascript/public/test/validators/numericality.js +140 -0
  83. data/test/javascript/public/test/validators/presence.js +15 -0
  84. data/test/javascript/public/test/validators/uniqueness.js +89 -0
  85. data/test/javascript/public/vendor/jquery.metadata.js +122 -0
  86. data/test/javascript/public/vendor/qunit.css +196 -0
  87. data/test/javascript/public/vendor/qunit.js +1374 -0
  88. data/test/javascript/server.rb +78 -0
  89. data/test/javascript/views/index.erb +20 -0
  90. data/test/javascript/views/layout.erb +21 -0
  91. data/test/middleware/cases/helper.rb +15 -0
  92. data/test/middleware/cases/test_middleware.rb +8 -0
  93. data/test/mongoid/cases/helper.rb +16 -0
  94. data/test/mongoid/cases/test_base.rb +15 -0
  95. data/test/mongoid/cases/test_middleware.rb +68 -0
  96. data/test/mongoid/cases/test_uniqueness_validator.rb +44 -0
  97. data/test/mongoid/models/book.rb +8 -0
  98. data/test/simple_form/cases/helper.rb +2 -0
  99. data/test/simple_form/cases/test_form_builder.rb +14 -0
  100. data/test/simple_form/cases/test_form_helper.rb +22 -0
  101. metadata +435 -0
@@ -0,0 +1,50 @@
1
+ module('Form Validate Pass Callback', {
2
+ setup: function() {
3
+ new_user = {
4
+ type: 'ActionView::Helpers::FormBuilder',
5
+ input_tag: '<div class="field_with_errors"><span id="input_tag" /><label for="user_name" class="message"></label></div>',
6
+ label_tag: '<div class="field_with_errors"><label id="label_tag" /></div>',
7
+ validators: {"user[name]":{"presence":{"message": "must be present"}}}
8
+ }
9
+
10
+ $('#qunit-fixture')
11
+ .append($('<span id="result" />'))
12
+ .append($('<form />', {
13
+ action: '/users',
14
+ 'data-validate': true,
15
+ method: 'post',
16
+ id: 'new_user'
17
+ }))
18
+ .find('form')
19
+ .append($('<input />', {
20
+ name: 'user[name]',
21
+ id: 'user_name',
22
+ 'data-validate': 'true',
23
+ type: 'text'
24
+ }))
25
+ .append($('<label for="user_name">Name</label>'));
26
+
27
+ clientSideValidations.callbacks.form.pass = function(form, message) {
28
+ $('#result').text('Form Validate Pass ' + form.attr('id'));
29
+ }
30
+ $('form#new_user').validate();
31
+ },
32
+ teardown: function() {
33
+ clientSideValidations.callbacks.form.pass = function(form, eventData) {}
34
+ }
35
+ });
36
+
37
+ test('runs callback', function() {
38
+ var form = $('form'), input = form.find('input');
39
+
40
+ equal($('#result').text(), '');
41
+
42
+ form.submit();
43
+ equal($('#result').text(), '');
44
+
45
+ input.val('test');
46
+ input.trigger('change');
47
+ form.submit();
48
+ equal($('#result').text(), 'Form Validate Pass new_user');
49
+ });
50
+
@@ -0,0 +1,66 @@
1
+ module('Validate Form', {
2
+ setup: function() {
3
+ new_user = {
4
+ type: 'ActionView::Helpers::FormBuilder',
5
+ input_tag: '<div class="field_with_errors"><span id="input_tag" /><label for="user_name" class="message"></label></div>',
6
+ label_tag: '<div class="field_with_errors"><label id="label_tag" /></div>',
7
+ validators: {'user[name]':{"presence":{"message": "must be present"}}}
8
+ }
9
+
10
+ $('#qunit-fixture')
11
+ .append($('<form />', {
12
+ action: '/users',
13
+ 'data-validate': true,
14
+ method: 'post',
15
+ id: 'new_user'
16
+ }))
17
+ .find('form')
18
+ .append($('<input />', {
19
+ name: 'user[name]',
20
+ id: 'user_name',
21
+ 'data-validate': 'true',
22
+ type: 'text'
23
+ }))
24
+ .append($('<label for="user_name">Name</label>'));
25
+ $('form#new_user').validate();
26
+ }
27
+ });
28
+
29
+ asyncTest('Validate form with invalid form', 4, function() {
30
+ var form = $('form#new_user'), input = form.find('input#user_name');
31
+ var label = $('label[for="user_name"]');
32
+
33
+ form.trigger('submit');
34
+ setTimeout(function() {
35
+ start();
36
+ ok(input.parent().hasClass('field_with_errors'));
37
+ ok(label.parent().hasClass('field_with_errors'));
38
+ ok(input.parent().find('label:contains("must be present")')[0]);
39
+ ok(!$('iframe').contents().find('p:contains("Form submitted")')[0]);
40
+ }, 30);
41
+ });
42
+
43
+ asyncTest('Validate form with valid form', 1, function() {
44
+ var form = $('form#new_user'), input = form.find('input#user_name');
45
+ input.val('Test');
46
+
47
+ form.trigger('submit');
48
+ setTimeout(function() {
49
+ start();
50
+ ok($('iframe').contents().find('p:contains("Form submitted")')[0]);
51
+ }, 30);
52
+ });
53
+
54
+ asyncTest('Validate form with an input changed to false', 1, function() {
55
+ var form = $('form#new_user'), input = form.find('input#user_name');
56
+ input.val('Test');
57
+ input.attr('changed', false);
58
+ input.attr('data-valid', true);
59
+
60
+ form.trigger('submit');
61
+ setTimeout(function() {
62
+ start();
63
+ ok($('iframe').contents().find('p:contains("Form submitted")')[0]);
64
+ }, 30);
65
+ });
66
+
@@ -0,0 +1,54 @@
1
+ module('Validate Formtastic', {
2
+ setup: function() {
3
+ new_user = {
4
+ type: 'Formtastic::SemanticFormBuilder',
5
+ inline_error_class: 'inline-errors',
6
+ validators: {
7
+ "user[name]":{"presence":{"message": "must be present"}, "format":{"message":"is invalid","with":/\d+/}}
8
+ }
9
+ }
10
+
11
+ $('#qunit-fixture')
12
+ .append($('<form />', {
13
+ action: '/users',
14
+ 'data-validate': true,
15
+ method: 'post',
16
+ id: 'new_user'
17
+ }))
18
+ .find('form')
19
+ .append('<li />').find('li')
20
+ .append($('<input />', {
21
+ name: 'user[name]',
22
+ id: 'user_name',
23
+ 'data-validate': 'true',
24
+ type: 'text'
25
+ }))
26
+ .append($('<label for="user_name">Name</label>'));
27
+ $('form#new_user').validate();
28
+ }
29
+ });
30
+
31
+ test('Validate error attaching and detaching', function() {
32
+ var form = $('form#new_user'), input = form.find('input#user_name');
33
+ var label = $('label[for="user_name"]');
34
+
35
+ input.trigger('focusout')
36
+ ok(input.parent().hasClass('error'));
37
+ ok(label.parent().hasClass('error'));
38
+ ok(input.parent().find('p.inline-errors:contains("must be present")')[0]);
39
+
40
+ input.val('abc')
41
+ input.trigger('change')
42
+ input.trigger('focusout')
43
+ ok(input.parent().hasClass('error'));
44
+ ok(label.parent().hasClass('error'));
45
+ ok(input.parent().find('p.inline-errors:contains("is invalid")')[0]);
46
+
47
+ input.val('123')
48
+ input.trigger('change')
49
+ input.trigger('focusout')
50
+ ok(!input.parent().hasClass('error'));
51
+ ok(!label.parent().hasClass('error'));
52
+ ok(!input.parent().find('p.inline-errors')[0]);
53
+ });
54
+
@@ -0,0 +1,57 @@
1
+ module('Validate SimpleForm', {
2
+ setup: function() {
3
+ new_user = {
4
+ type: 'SimpleForm::FormBuilder',
5
+ error_class: 'error',
6
+ error_tag: 'span',
7
+ wrapper_error_class: 'field_with_errors',
8
+ wrapper_tag: 'div',
9
+ validators: {
10
+ "user[name]":{"presence":{"message": "must be present"}, "format":{"message":"is invalid","with":/\d+/}}
11
+ }
12
+ }
13
+
14
+ $('#qunit-fixture')
15
+ .append($('<form />', {
16
+ action: '/users',
17
+ 'data-validate': true,
18
+ method: 'post',
19
+ id: 'new_user'
20
+ }))
21
+ .find('form')
22
+ .append('<div />').find('div')
23
+ .append($('<input />', {
24
+ name: 'user[name]',
25
+ id: 'user_name',
26
+ 'data-validate': 'true',
27
+ type: 'text'
28
+ }))
29
+ .append($('<label for="user_name">Name</label>'));
30
+ $('form#new_user').validate();
31
+ }
32
+ });
33
+
34
+ test('Validate error attaching and detaching', function() {
35
+ var form = $('form#new_user'), input = form.find('input#user_name');
36
+ var label = $('label[for="user_name"]');
37
+
38
+ input.trigger('focusout');
39
+ ok(input.parent().hasClass('field_with_errors'));
40
+ ok(label.parent().hasClass('field_with_errors'));
41
+ ok(input.parent().find('span.error:contains("must be present")')[0]);
42
+
43
+ input.val('abc')
44
+ input.trigger('change')
45
+ input.trigger('focusout')
46
+ ok(input.parent().hasClass('field_with_errors'));
47
+ ok(label.parent().hasClass('field_with_errors'));
48
+ ok(input.parent().find('span.error:contains("is invalid")')[0]);
49
+
50
+ input.val('123')
51
+ input.trigger('change')
52
+ input.trigger('focusout')
53
+ ok(!input.parent().hasClass('field_with_errors'));
54
+ ok(!label.parent().hasClass('field_with_errors'));
55
+ ok(!input.parent().find('span.error')[0]);
56
+ });
57
+
@@ -0,0 +1,15 @@
1
+ // hijacks normal form submit; lets it submit to an iframe to prevent
2
+ // navigating away from the test suite
3
+ $(document).bind('submit', function(e) {
4
+ if (!e.isDefaultPrevented()) {
5
+ var form = $(e.target), action = form.attr('action'),
6
+ name = 'form-frame' + jQuery.guid++,
7
+ iframe = $('<iframe name="' + name + '" />');
8
+
9
+ if (action.indexOf('iframe') < 0) form.attr('action', action + '?iframe=true')
10
+ form.attr('target', name);
11
+ $('#qunit-fixture').append(iframe);
12
+ form.trigger('iframe:loading');
13
+ }
14
+ });
15
+
@@ -0,0 +1,144 @@
1
+ module('Validate Element', {
2
+ setup: function() {
3
+ new_user = {
4
+ type: 'ActionView::Helpers::FormBuilder',
5
+ input_tag: '<div class="field_with_errors"><span id="input_tag" /><label for="user_name" class="message"></label></div>',
6
+ label_tag: '<div class="field_with_errors"><label id="label_tag" /></div>',
7
+ validators: {
8
+ 'user[name]':{"presence":{"message": "must be present"}, "format":{"message":"is invalid","with":/\d+/}},
9
+ 'user[password]':{"confirmation":{"message": "must match confirmation"}},
10
+ 'user[agree]':{"acceptance": {"message": "must be accepted"}},
11
+ 'user[email]':{"uniqueness":{"message": "must be unique"},"presence":{"message": "must be present"}}
12
+ }
13
+ }
14
+
15
+ $('#qunit-fixture')
16
+ .append($('<form />', {
17
+ action: '/users',
18
+ 'data-validate': true,
19
+ method: 'post',
20
+ id: 'new_user'
21
+ }))
22
+ .find('form')
23
+ .append($('<label for="user_name">Name</label>'))
24
+ .append($('<input />', {
25
+ name: 'user[name]',
26
+ id: 'user_name',
27
+ 'data-validate': 'true',
28
+ type: 'text'
29
+ }))
30
+ .append($('<label for="user_password">Password</label>'))
31
+ .append($('<input />', {
32
+ name: 'user[password]',
33
+ id: 'user_password',
34
+ 'data-validate': 'true',
35
+ type: 'password'
36
+ }))
37
+ .append($('<label for="user_password_confirmation">Password Confirmation</label>'))
38
+ .append($('<input />', {
39
+ name: 'user[password_confirmation]',
40
+ id: 'user_password_confirmation',
41
+ type: 'password'
42
+ }))
43
+ .append($('<label for="user_agree">Agree</label>'))
44
+ .append($('<input />', {
45
+ name: 'user[agree]',
46
+ id: 'user_agree',
47
+ 'data-validate': 'true',
48
+ type: 'checkbox',
49
+ value: 1
50
+ }))
51
+ .append($('<input />', {
52
+ name: 'user[email]',
53
+ id: 'user_email',
54
+ 'data-validate': 'true',
55
+ type: 'text'
56
+ }))
57
+
58
+ $('form#new_user').validate();
59
+ }
60
+ });
61
+
62
+ test('Validate when focusouting', function() {
63
+ var form = $('form#new_user'), input = form.find('input#user_name');
64
+ var label = $('label[for="user_name"]');
65
+
66
+ input.trigger('focusout');
67
+ ok(input.parent().hasClass('field_with_errors'));
68
+ ok(label.parent().hasClass('field_with_errors'));
69
+ });
70
+
71
+ test('Validate when checkbox is clicked', function() {
72
+ var form = $('form#new_user'), input = form.find('input#user_agree');
73
+ var label = $('label[for="user_agree"]');
74
+
75
+ input.attr('checked', false)
76
+ input.trigger('click');
77
+ ok(input.parent().hasClass('field_with_errors'));
78
+ ok(label.parent().hasClass('field_with_errors'));
79
+ });
80
+
81
+ test('Validate when focusout on confirmation', function() {
82
+ var form = $('form#new_user'), password = form.find('input#user_password'), confirmation = form.find('input#user_password_confirmation');
83
+ var label = $('label[for="user_password"]');
84
+
85
+ password.val('password');
86
+ confirmation.trigger('focusout');
87
+ ok(password.parent().hasClass('field_with_errors'));
88
+ ok(label.parent().hasClass('field_with_errors'));
89
+ });
90
+
91
+ test('Validate when keyup on confirmation', function() {
92
+ var form = $('form#new_user'), password = form.find('input#user_password'), confirmation = form.find('input#user_password_confirmation');
93
+ var label = $('label[for="user_password"]');
94
+
95
+ password.val('password');
96
+
97
+ confirmation.trigger('keyup');
98
+ ok(password.parent().hasClass('field_with_errors'));
99
+ ok(label.parent().hasClass('field_with_errors'));
100
+
101
+ confirmation.val('password')
102
+ confirmation.trigger('keyup');
103
+ ok(!password.parent().hasClass('field_with_errors'));
104
+ ok(!label.parent().hasClass('field_with_errors'));
105
+ });
106
+
107
+ test('Forcing remote validators to run last', function() {
108
+ var form = $('form#new_user'), input = form.find('input#user_email');
109
+
110
+ input.trigger('focusout');
111
+ equal(input.parent().find('label').text(), "must be present")
112
+ });
113
+
114
+ test("Don't validate when value hasn't changed", function() {
115
+ var form = $('form#new_user'), input = form.find('input#user_name');
116
+ var label = $('label[for="user_name"]');
117
+
118
+ input.trigger('focusout');
119
+ ok(input.parent().hasClass('field_with_errors'));
120
+ ok(label.parent().hasClass('field_with_errors'));
121
+
122
+ input.val('123');
123
+ input.trigger('focusout');
124
+ ok(input.parent().hasClass('field_with_errors'));
125
+ ok(label.parent().hasClass('field_with_errors'));
126
+
127
+ input.trigger('change');
128
+ input.trigger('focusout');
129
+ ok(!input.parent().hasClass('field_with_errors'));
130
+ ok(!label.parent().hasClass('field_with_errors'));
131
+ });
132
+
133
+ test('Validate when error message needs to change', function() {
134
+ var form = $('form#new_user'), input = form.find('input#user_name');
135
+ var label = $('label[for="user_name"]');
136
+
137
+ input.trigger('focusout');
138
+ equal(input.parent().find('label.message').text(), "must be present");
139
+ input.val('abc');
140
+ input.trigger('change')
141
+ input.trigger('focusout');
142
+ equal(input.parent().find('label.message').text(), "is invalid");
143
+ });
144
+
@@ -0,0 +1,42 @@
1
+ module('Acceptance options');
2
+
3
+ test('when checkbox and checked', function() {
4
+ var element = $('<input type="checkbox" />');
5
+ var options = { message: "failed validation" };
6
+ element.attr('checked', true)
7
+ equal(clientSideValidations.validators.local.acceptance(element, options), undefined);
8
+ });
9
+
10
+ test('when checkbox and not checked', function() {
11
+ var element = $('<input type="checkbox" />');
12
+ var options = { message: "failed validation" };
13
+ equal(clientSideValidations.validators.local.acceptance(element, options), "failed validation");
14
+ });
15
+
16
+ test('when text and value default of 1', function() {
17
+ var element = $('<input type="text" />');
18
+ var options = { message: "failed validation" };
19
+ element.val("1");
20
+ equal(clientSideValidations.validators.local.acceptance(element, options), undefined);
21
+ });
22
+
23
+ test('when text and value 2 and accept value is 2', function() {
24
+ var element = $('<input type="text" />');
25
+ var options = { message: "failed validation", accept: 1 };
26
+ element.val("1");
27
+ equal(clientSideValidations.validators.local.acceptance(element, options), undefined);
28
+ });
29
+
30
+ test('when text and value empty', function() {
31
+ var element = $('<input type="text" />');
32
+ var options = { message: "failed validation" };
33
+ equal(clientSideValidations.validators.local.acceptance(element, options), "failed validation");
34
+ });
35
+
36
+ test('when text and value 1 and accept value is 2', function() {
37
+ var element = $('<input type="text" />');
38
+ var options = { message: "failed validation", accept: 2 };
39
+ element.val("1");
40
+ equal(clientSideValidations.validators.local.acceptance(element, options), "failed validation");
41
+ });
42
+
@@ -0,0 +1,25 @@
1
+ module('Confirmation options', {
2
+ setup: function() {
3
+ $('#qunit-fixture')
4
+ .append('<input id="password" type="password" />')
5
+ .append('<input id="password_confirmation" type="password" />')
6
+ }
7
+ });
8
+
9
+ test('when values match', function() {
10
+ var password_element = $('#password');
11
+ var password_confirmation_element = $('#password_confirmation');
12
+ var options = { message: "failed validation" };
13
+ password_element.val('test');
14
+ password_confirmation_element.val('test');
15
+ equal(clientSideValidations.validators.local.confirmation(password_element, options), undefined);
16
+ });
17
+
18
+ test('when values match', function() {
19
+ var password_element = $('#password');
20
+ var password_confirmation_element = $('#password_confirmation');
21
+ var options = { message: "failed validation" };
22
+ password_element.val('test');
23
+ password_confirmation_element.val('bad test');
24
+ equal(clientSideValidations.validators.local.confirmation(password_element, options), "failed validation");
25
+ });