active_form 0.0.1

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 (184) hide show
  1. data.tar.gz.sig +2 -0
  2. data/History.txt +4 -0
  3. data/License.txt +20 -0
  4. data/MIT-LICENSE +19 -0
  5. data/Manifest.txt +181 -0
  6. data/README.txt +1 -0
  7. data/Rakefile +4 -0
  8. data/config/hoe.rb +71 -0
  9. data/config/requirements.rb +17 -0
  10. data/init.rb +5 -0
  11. data/lib/active_form.rb +86 -0
  12. data/lib/active_form/core_extensions.rb +179 -0
  13. data/lib/active_form/definition.rb +72 -0
  14. data/lib/active_form/element.rb +50 -0
  15. data/lib/active_form/elements/base.rb +67 -0
  16. data/lib/active_form/elements/builder.rb +103 -0
  17. data/lib/active_form/elements/button.rb +15 -0
  18. data/lib/active_form/elements/checkbox.rb +18 -0
  19. data/lib/active_form/elements/file.rb +15 -0
  20. data/lib/active_form/elements/hidden.rb +9 -0
  21. data/lib/active_form/elements/image.rb +7 -0
  22. data/lib/active_form/elements/input.rb +23 -0
  23. data/lib/active_form/elements/password.rb +12 -0
  24. data/lib/active_form/elements/radio.rb +18 -0
  25. data/lib/active_form/elements/reset.rb +15 -0
  26. data/lib/active_form/elements/section.rb +37 -0
  27. data/lib/active_form/elements/select.rb +42 -0
  28. data/lib/active_form/elements/submit.rb +19 -0
  29. data/lib/active_form/elements/text.rb +9 -0
  30. data/lib/active_form/elements/textarea.rb +18 -0
  31. data/lib/active_form/errors.rb +73 -0
  32. data/lib/active_form/facets/checkbox_group.rb +11 -0
  33. data/lib/active_form/facets/collection_input.rb +96 -0
  34. data/lib/active_form/facets/radio_group.rb +11 -0
  35. data/lib/active_form/facets/select_date.rb +10 -0
  36. data/lib/active_form/facets/select_datetime.rb +10 -0
  37. data/lib/active_form/facets/select_day.rb +17 -0
  38. data/lib/active_form/facets/select_from_model.rb +60 -0
  39. data/lib/active_form/facets/select_hour.rb +17 -0
  40. data/lib/active_form/facets/select_minute.rb +17 -0
  41. data/lib/active_form/facets/select_month.rb +46 -0
  42. data/lib/active_form/facets/select_numeric_range.rb +59 -0
  43. data/lib/active_form/facets/select_second.rb +17 -0
  44. data/lib/active_form/facets/select_time.rb +10 -0
  45. data/lib/active_form/facets/select_timebased.rb +145 -0
  46. data/lib/active_form/facets/select_weekday.rb +46 -0
  47. data/lib/active_form/facets/select_year.rb +24 -0
  48. data/lib/active_form/mixins/attribute_methods.rb +33 -0
  49. data/lib/active_form/mixins/casting.rb +152 -0
  50. data/lib/active_form/mixins/collection_element_methods.rb +204 -0
  51. data/lib/active_form/mixins/common_methods.rb +350 -0
  52. data/lib/active_form/mixins/container_methods.rb +417 -0
  53. data/lib/active_form/mixins/css_methods.rb +70 -0
  54. data/lib/active_form/mixins/element_methods.rb +314 -0
  55. data/lib/active_form/mixins/javascript_methods.rb +99 -0
  56. data/lib/active_form/mixins/loader_methods.rb +72 -0
  57. data/lib/active_form/mixins/option_element_methods.rb +61 -0
  58. data/lib/active_form/mixins/validation_methods.rb +253 -0
  59. data/lib/active_form/validator.rb +47 -0
  60. data/lib/active_form/validators/alpha.rb +9 -0
  61. data/lib/active_form/validators/alphanum.rb +9 -0
  62. data/lib/active_form/validators/base.rb +132 -0
  63. data/lib/active_form/validators/digits.rb +9 -0
  64. data/lib/active_form/validators/email.rb +29 -0
  65. data/lib/active_form/validators/format.rb +15 -0
  66. data/lib/active_form/validators/length_range.rb +24 -0
  67. data/lib/active_form/validators/number.rb +9 -0
  68. data/lib/active_form/validators/option_count.rb +24 -0
  69. data/lib/active_form/validators/proc.rb +22 -0
  70. data/lib/active_form/validators/required.rb +9 -0
  71. data/lib/active_form/validators/set.rb +21 -0
  72. data/lib/active_form/validators/time_range.rb +30 -0
  73. data/lib/active_form/validators/uri.rb +54 -0
  74. data/lib/active_form/version.rb +9 -0
  75. data/lib/active_form/views/fieldsets.rb +34 -0
  76. data/lib/active_form/views/plain.rb +32 -0
  77. data/lib/active_form/views/tables.rb +28 -0
  78. data/lib/active_form/widget.rb +43 -0
  79. data/lib/active_form/widgets/base.rb +28 -0
  80. data/lib/loob/uri_validator.rb +140 -0
  81. data/lib/rails/acts_as_dropdown/MIT-LICENSE +20 -0
  82. data/lib/rails/acts_as_dropdown/acts_as_dropdown.rb +119 -0
  83. data/lib/rails/acts_as_dropdown/dropdown.rb +27 -0
  84. data/lib/rails/controller_helper.rb +19 -0
  85. data/lib/rails/model/loader.rb +206 -0
  86. data/lib/rails/view_helper.rb +20 -0
  87. data/samples/html/css/style.css +175 -0
  88. data/samples/html/js/effects.js +958 -0
  89. data/samples/html/js/prototype.js +2006 -0
  90. data/samples/html/js/validation.js +228 -0
  91. data/samples/html/plain_view.html +77 -0
  92. data/samples/html/sample001.html +158 -0
  93. data/samples/html/sample002.html +76 -0
  94. data/samples/html/sample003.html +34 -0
  95. data/samples/layouts/default.rhtml +18 -0
  96. data/samples/layouts/plain.rhtml +21 -0
  97. data/samples/layouts/sample003.rhtml +25 -0
  98. data/samples/plain_view.rb +58 -0
  99. data/samples/sample001.rb +111 -0
  100. data/samples/sample002.rb +92 -0
  101. data/samples/sample003.rb +30 -0
  102. data/script/destroy +14 -0
  103. data/script/generate +14 -0
  104. data/script/txt2html +74 -0
  105. data/setup.rb +1585 -0
  106. data/tasks/deployment.rake +34 -0
  107. data/tasks/environment.rake +7 -0
  108. data/tasks/website.rake +17 -0
  109. data/test/elements/test_base_element.rb +159 -0
  110. data/test/elements/test_builder_element.rb +81 -0
  111. data/test/elements/test_button_element.rb +12 -0
  112. data/test/elements/test_checkbox_element.rb +233 -0
  113. data/test/elements/test_file_element.rb +20 -0
  114. data/test/elements/test_hidden_element.rb +11 -0
  115. data/test/elements/test_image_element.rb +11 -0
  116. data/test/elements/test_input_element.rb +39 -0
  117. data/test/elements/test_password_element.rb +16 -0
  118. data/test/elements/test_radio_element.rb +197 -0
  119. data/test/elements/test_reset_element.rb +12 -0
  120. data/test/elements/test_section_element.rb +162 -0
  121. data/test/elements/test_select_element.rb +364 -0
  122. data/test/elements/test_submit_element.rb +12 -0
  123. data/test/elements/test_text_element.rb +91 -0
  124. data/test/elements/test_textarea_element.rb +23 -0
  125. data/test/facets/test_checkbox_group_element.rb +388 -0
  126. data/test/facets/test_radio_group_element.rb +312 -0
  127. data/test/facets/test_select_date_element.rb +211 -0
  128. data/test/facets/test_select_datetime_element.rb +56 -0
  129. data/test/facets/test_select_day_element.rb +37 -0
  130. data/test/facets/test_select_from_model_element.rb +86 -0
  131. data/test/facets/test_select_hour_element.rb +37 -0
  132. data/test/facets/test_select_minute_element.rb +52 -0
  133. data/test/facets/test_select_month_element.rb +79 -0
  134. data/test/facets/test_select_numeric_range_element.rb +14 -0
  135. data/test/facets/test_select_second_element.rb +48 -0
  136. data/test/facets/test_select_time_element.rb +148 -0
  137. data/test/facets/test_select_weekday_element.rb +71 -0
  138. data/test/facets/test_select_year_element.rb +73 -0
  139. data/test/fixtures/author.rb +11 -0
  140. data/test/fixtures/authors.yml +0 -0
  141. data/test/fixtures/book.rb +14 -0
  142. data/test/fixtures/books.yml +8 -0
  143. data/test/fixtures/categories.yml +0 -0
  144. data/test/fixtures/categorization.rb +2 -0
  145. data/test/fixtures/categorizations.yml +0 -0
  146. data/test/fixtures/category.rb +8 -0
  147. data/test/fixtures/publisher.rb +5 -0
  148. data/test/fixtures/publishers.yml +10 -0
  149. data/test/fixtures/schema.rb +43 -0
  150. data/test/rails/test_model_autodefinition.rb +121 -0
  151. data/test/rails/test_model_loader.rb +61 -0
  152. data/test/resources/elements/chunky.rb +11 -0
  153. data/test/resources/forms/demo.rb +5 -0
  154. data/test/resources/models/book.rb +8 -0
  155. data/test/resources/models/register_publisher.rb +5 -0
  156. data/test/resources/sections/demo.rb +6 -0
  157. data/test/resources/sections/foo.rb +6 -0
  158. data/test/resources/validators/foo.rb +9 -0
  159. data/test/resources/widgets/custom.rb +13 -0
  160. data/test/test_active_form.rb +1050 -0
  161. data/test/test_casting.rb +124 -0
  162. data/test/test_definition.rb +68 -0
  163. data/test/test_definition_class.rb +118 -0
  164. data/test/test_element_class.rb +201 -0
  165. data/test/test_helper.rb +74 -0
  166. data/test/test_javascript.rb +234 -0
  167. data/test/test_load_definition.rb +68 -0
  168. data/test/test_load_element.rb +35 -0
  169. data/test/test_load_section_element.rb +43 -0
  170. data/test/test_load_validator.rb +31 -0
  171. data/test/test_load_widget.rb +93 -0
  172. data/test/test_validation.rb +722 -0
  173. data/test/validators/test_validates_as_alpha.rb +26 -0
  174. data/test/validators/test_validates_as_alphanum.rb +26 -0
  175. data/test/validators/test_validates_as_digits.rb +26 -0
  176. data/test/validators/test_validates_as_email.rb +29 -0
  177. data/test/validators/test_validates_as_number.rb +26 -0
  178. data/test/validators/test_validates_as_uri.rb +128 -0
  179. data/test/validators/test_validates_with_format.rb +26 -0
  180. data/test/validators/test_validates_within_length_range.rb +46 -0
  181. data/test/validators/test_validates_within_set.rb +46 -0
  182. data/test/validators/test_validates_within_time_range.rb +53 -0
  183. metadata +307 -0
  184. metadata.gz.sig +4 -0
@@ -0,0 +1,31 @@
1
+ require 'test_helper'
2
+
3
+ class TestLoadValidator < Test::Unit::TestCase
4
+
5
+ def setup
6
+ ActiveForm::Validator.load_paths << File.join(File.dirname(__FILE__), 'resources', 'validators')
7
+ end
8
+
9
+ def test_load_paths
10
+ assert_equal 2, ActiveForm::Validator.load_paths.length
11
+ assert File.directory?(ActiveForm::Validator.load_paths.first)
12
+ assert File.directory?(ActiveForm::Validator.load_paths.last)
13
+ end
14
+
15
+ def test_assign_and_use_validator
16
+ form = ActiveForm::compose :form do |f|
17
+ f.text_element :elem_a, :label => 'A', :value => 'no foo' do |e|
18
+ e.validates_as_required
19
+ e.validates_as_foo
20
+ end
21
+ end
22
+ assert_equal ["required", "foo"], form[:elem_a].validators.collect(&:code)
23
+ assert !form.validate
24
+ assert_equal ["A: should be foo-matic!"], form[:elem_a].errors.collect(&:msg)
25
+ end
26
+
27
+ def teardown
28
+ ActiveForm::Validator.load_paths.delete_at(1)
29
+ end
30
+
31
+ end
@@ -0,0 +1,93 @@
1
+ require 'test_helper'
2
+
3
+ class TestLoadWidget < Test::Unit::TestCase
4
+
5
+ def setup
6
+ ActiveForm::Widget.load_paths << File.join(File.dirname(__FILE__), 'resources', 'widgets')
7
+ end
8
+
9
+ def test_load_paths
10
+ assert_equal 2, ActiveForm::Widget.load_paths.length
11
+ assert File.directory?(ActiveForm::Widget.load_paths[0])
12
+ assert File.directory?(ActiveForm::Widget.load_paths[1])
13
+ end
14
+
15
+ def test_load_and_build
16
+ assert_equal ActiveForm::Widget::Custom, ActiveForm::Widget::get(:custom)
17
+ elem = ActiveForm::Widget::build(:custom)
18
+ assert_kind_of ActiveForm::Widget::Custom, elem
19
+ end
20
+
21
+ def test_add_widget
22
+ form = ActiveForm::compose :form do |f|
23
+ f.text_element :name
24
+ f.custom_widget :my_widget
25
+ end
26
+ assert_equal [:text, :custom_widget], form.collect(&:element_type)
27
+ end
28
+
29
+ def test_add_widget_as_element_at_top
30
+ form = ActiveForm::compose :form do |f|
31
+ f.text_element :name
32
+ end
33
+ form.insert_element_at_top(ActiveForm::Widget::build(:custom))
34
+ assert_equal [:custom_widget, :text], form.collect(&:element_type)
35
+ end
36
+
37
+ def test_widget_to_html
38
+ users = [ { :id => 1, :firstname => 'Fred', :lastname => 'Flintstone' }, { :id => 2, :firstname => 'Barney', :lastname => 'Rubble' } ]
39
+ form = ActiveForm::compose :form do |f|
40
+ f.section :users do |s|
41
+ users.each do |user|
42
+ s.custom_widget "user_#{user[:id]}", :values => user
43
+ end
44
+ end
45
+ f.submit_element
46
+ end
47
+ expected = %|<form action="#form" class="active_form" id="form" method="post">
48
+ <table>
49
+ <tr>
50
+ <td>
51
+ <label for="form_users_user_1_firstname">Firstname</label>
52
+ </td>
53
+ <td>
54
+ <label for="form_users_user_1_lastname">Lastname</label>
55
+ </td>
56
+ </tr>
57
+ <tr>
58
+ <td>
59
+ <input class="elem_text" id="form_users_user_1_firstname" name="form[users][user_1][firstname]" size="30" title="First Name" type="text" value="Fred"/>
60
+ </td>
61
+ <td>
62
+ <input class="elem_text" id="form_users_user_1_lastname" name="form[users][user_1][lastname]" size="30" title="Last Name" type="text" value="Flintstone"/>
63
+ </td>
64
+ </tr>
65
+ </table>
66
+ <table>
67
+ <tr>
68
+ <td>
69
+ <label for="form_users_user_2_firstname">Firstname</label>
70
+ </td>
71
+ <td>
72
+ <label for="form_users_user_2_lastname">Lastname</label>
73
+ </td>
74
+ </tr>
75
+ <tr>
76
+ <td>
77
+ <input class="elem_text" id="form_users_user_2_firstname" name="form[users][user_2][firstname]" size="30" title="First Name" type="text" value="Barney"/>
78
+ </td>
79
+ <td>
80
+ <input class="elem_text" id="form_users_user_2_lastname" name="form[users][user_2][lastname]" size="30" title="Last Name" type="text" value="Rubble"/>
81
+ </td>
82
+ </tr>
83
+ </table>
84
+ <input class="elem_submit" id="form_submit" name="form[submit]" type="submit" value="Submit"/>
85
+ </form>\n|
86
+ assert_equal expected, form.to_html
87
+ end
88
+
89
+ def teardown
90
+ ActiveForm::Widget.load_paths.delete_at(1)
91
+ end
92
+
93
+ end
@@ -0,0 +1,722 @@
1
+ require 'test_helper'
2
+
3
+ ActiveForm::Validator::Base.create :special do
4
+
5
+ default_message "%s: isn't all that great"
6
+
7
+ end
8
+
9
+ class TestValidation < Test::Unit::TestCase
10
+
11
+ def test_create_and_build_validator
12
+ assert_equal ActiveForm::Validator::Special, ActiveForm::Validator::get(:special)
13
+ validator = ActiveForm::Validator::build(:special)
14
+ assert_kind_of ActiveForm::Validator::Special, validator
15
+ assert_equal "%s: isn't all that great", validator.message
16
+ ActiveForm::Validator::get(:special).default_message = "%s: isn't so special"
17
+ assert_equal "%s: isn't so special", validator.message
18
+ end
19
+
20
+ def test_validated
21
+ form = ActiveForm::compose :form do |f|
22
+ f.text_element :name
23
+ f.text_element :language
24
+ f.submit_element :send
25
+ end
26
+ assert !form.submitted?
27
+ assert !form.validated?
28
+ assert form.validate
29
+ # coming from click on submit button
30
+ form[:send].value = 'Send'
31
+ assert form.submitted?
32
+ assert form.validated?
33
+ assert form.validate
34
+ end
35
+
36
+ def test_define_class_level_validation
37
+ ActiveForm::Definition.define_validation do |form|
38
+ form.each do |elem|
39
+ elem.errors.add('%s is empty', 'empty') if elem.blank?
40
+ end
41
+ end
42
+
43
+ ActiveForm::Element::Base.define_validation do |elem|
44
+ elem.errors.add("%s can't be numeric", 'non-numeric') if elem.value.to_s.match(/^[0-9]+$/)
45
+ end
46
+
47
+ form = ActiveForm::compose :form do |f|
48
+ f.text_element :elem_a
49
+ f.text_element :elem_b
50
+ end
51
+
52
+ assert !form.validate
53
+ assert_equal 2, form.element_errors.length
54
+ assert_equal "Elem A is empty", form[:elem_a].errors.first.message
55
+ assert_equal "Elem B is empty", form[:elem_b].errors.first.message
56
+
57
+ form.params = { :form => { :elem_a => 'a', :elem_b => 'b' } }
58
+
59
+ assert form.validate
60
+ assert_equal 0, form.element_errors.length
61
+
62
+ form.params = { :form => { :elem_a => 2 } }
63
+
64
+ assert !form.validate
65
+ assert_equal 1, form.element_errors.length
66
+ assert_equal "Elem A can't be numeric", form[:elem_a].errors.first.message
67
+
68
+ ActiveForm::Definition.reset_validation
69
+ ActiveForm::Element::Base.reset_validation
70
+ end
71
+
72
+ def test_define_container_validation
73
+ form = ActiveForm::compose :form do |f|
74
+ f.text_element :elem_a
75
+ f.text_element :elem_b
76
+
77
+ f.define_validation do |elem|
78
+ elem.errors.add('empty elements found', 'empty') if elem[:elem_a].blank? || elem[:elem_b].blank?
79
+ end
80
+ end
81
+ assert !form.validate
82
+ assert !form.valid?
83
+ assert_equal 1, form.errors.length
84
+ assert_equal 1, form.element_errors.length
85
+ assert form.errors.collect(&:code).include?('empty')
86
+ assert form.runtime_css_class.include?('validation-failed')
87
+ assert form.label_css_class.include?('validation-failed')
88
+ form[:elem_a].element_value = 'non-empty'
89
+ form[:elem_b].element_value = 'non-empty'
90
+ assert form.validate
91
+ assert form.valid?
92
+ assert_equal 0, form.element_errors.length
93
+ assert !form.runtime_css_class.include?('validation-failed')
94
+ end
95
+
96
+ def test_define_validation_add_error_to_element
97
+ form = ActiveForm::compose :form do |f|
98
+ f.text_element :elem_a
99
+ f.text_element :elem_b
100
+
101
+ f.define_validation do |elem|
102
+ elem[:elem_a].errors.add('%s is empty', 'empty') if elem[:elem_a].blank?
103
+ elem[:elem_b].errors.add('%s is empty', 'empty') if elem[:elem_b].blank?
104
+ end
105
+ end
106
+ assert !form.validate
107
+ assert !form.valid?
108
+ assert_equal 2, form.element_errors.length
109
+ assert form.element_errors.collect(&:code).include?('empty')
110
+ assert form.runtime_css_class.include?('validation-failed')
111
+ assert !form[:elem_a].valid?
112
+ assert form[:elem_a].runtime_css_class.include?('validation-failed')
113
+ assert !form[:elem_b].valid?
114
+ assert form[:elem_b].runtime_css_class.include?('validation-failed')
115
+ form[:elem_a].element_value = 'non-empty'
116
+ assert !form.validate
117
+ assert !form.valid?
118
+ assert_equal 1, form.element_errors.length
119
+ assert form.runtime_css_class.include?('validation-failed')
120
+ assert form[:elem_a].valid?
121
+ assert !form[:elem_a].runtime_css_class.include?('validation-failed')
122
+ assert !form[:elem_b].valid?
123
+ assert form[:elem_b].runtime_css_class.include?('validation-failed')
124
+ form[:elem_b].element_value = 'non-empty'
125
+ assert form.validate
126
+ assert form.valid?
127
+ assert_equal 0, form.element_errors.length
128
+ assert !form.runtime_css_class.include?('validation-failed')
129
+ end
130
+
131
+ def test_clear_validations
132
+ form = ActiveForm::compose :form do |f|
133
+ f.text_element :elem_a
134
+ f.text_element :elem_b
135
+
136
+ f.define_validation do |elem|
137
+ elem[:elem_a].errors.add('%s is empty', 'empty') if elem[:elem_a].blank?
138
+ elem[:elem_b].errors.add('%s is empty', 'empty') if elem[:elem_b].blank?
139
+ end
140
+ end
141
+ assert !(form.validate && form.valid?)
142
+ assert_equal 2, form.element_errors.length
143
+ form.clear_validations!
144
+ assert_equal 0, form.element_errors.length
145
+ assert !(form.validate && form.valid?)
146
+ assert_equal 2, form.element_errors.length
147
+ end
148
+
149
+ def test_validation_exception
150
+ form = ActiveForm::compose :form do |f|
151
+ f.text_element :elem_a
152
+ f.text_element :elem_b
153
+ f.define_validation do |elem|
154
+ elem[:elem_a].errors.add('%s is empty', 'empty') if elem[:elem_a].blank?
155
+ elem[:elem_b].errors.add('%s is empty', 'empty') if elem[:elem_b].blank?
156
+ end
157
+ end
158
+ assert_raises(ActiveForm::ValidationException) { form.validate! }
159
+ end
160
+
161
+ def test_define_element_validation
162
+ form = ActiveForm::compose :form do |f|
163
+ f.text_element :elem_a do |e|
164
+ e.define_validation do |elem|
165
+ elem.errors.add('%s is empty', 'empty') if elem.blank?
166
+ elem.errors.add('%s is not numeric', 'numeric') unless value.to_s.match(/^[0-9]+$/)
167
+ end
168
+ end
169
+ f.text_element :elem_b
170
+ end
171
+ assert !form.validate
172
+ assert_equal 0, form.errors.length
173
+ assert_equal 2, form.element_errors.length
174
+ assert_equal ['empty', 'numeric'], form.element_errors.collect(&:code)
175
+ assert_equal 1, form.initial_errors.length
176
+ assert_equal ['empty'], form.initial_errors.collect(&:code)
177
+ assert_equal 2, form[:elem_a].element_errors.length
178
+ assert_equal ['empty', 'numeric'], form[:elem_a].element_errors.collect(&:code)
179
+ assert_equal 1, form[:elem_a].initial_errors.length
180
+ assert_equal ['empty'], form[:elem_a].initial_errors.collect(&:code)
181
+ end
182
+
183
+ def test_create_proc_validator
184
+ form = ActiveForm::compose :form do |f|
185
+ f.text_element :elem_a do |e|
186
+ e.validates_with_proc :msg => '%s: proc validation failed' do |v|
187
+ v.element.errors.add(v.message) unless v.value == 123
188
+ end
189
+ end
190
+ end
191
+ assert !form.validate
192
+ assert_equal 'Elem A: proc validation failed', form[:elem_a].errors.first.message
193
+ form[:elem_a].element_value = 123
194
+ assert form.validate
195
+ end
196
+
197
+ def test_assign_proc_validator
198
+ one_two_three = lambda { |v| v.element.errors.add(v.message, v.code) unless v.value == 123 }
199
+ form = ActiveForm::compose :form do |f|
200
+ f.text_element :elem_a do |e|
201
+ e.validates_with_proc :msg => '%s: proc validation failed', :proc => one_two_three
202
+ end
203
+ end
204
+ assert !form.validate
205
+ assert_equal 'Elem A: proc validation failed', form[:elem_a].errors.first.message
206
+ form[:elem_a].element_value = 123
207
+ assert form.validate
208
+ end
209
+
210
+ def test_validation_messages
211
+ flunker = lambda { |v| v.element.errors.add(v.message, v.code) }
212
+ form = ActiveForm::compose :form do |f|
213
+ f.text_element :elem_a, :label => 'Result', :value => 'foo' do |e|
214
+ e.validates_with_proc :msg => '%s: flunked test (value=%s)', :proc => flunker
215
+ e.validates_with_proc :msg => 'value "%2$s" incorrect for %1$s-field', :proc => flunker
216
+ end
217
+ end
218
+ assert !form.validate
219
+ assert_equal 'Result: flunked test (value=foo)', form[:elem_a].errors[0].message
220
+ assert_equal 'value "foo" incorrect for Result-field', form[:elem_a].errors[1].message
221
+ end
222
+
223
+ def test_localized_validation_messages
224
+ translations = {
225
+ 'form_elem_a_label' => 'Resultaat',
226
+ 'form_elem_a_validates_one' => 'een: advies voor %s-veld',
227
+ 'form_elem_a_validates_two' => 'twee: advies voor %s-veld'
228
+ }
229
+
230
+ flunker = lambda { |v| v.element.errors.add(v.message, v.code) }
231
+ form = ActiveForm::compose :form do |f|
232
+ f.define_localizer { |formname, elemname, key| translations[ [formname, elemname, key].compact.join('_') ] }
233
+ f.text_element :elem_a, :label => 'Result', :value => 'foo' do |e|
234
+ e.validates_with_proc :code => 'one', :msg => '%s: flunked test (%s)', :proc => flunker
235
+ e.validates_with_proc :code => 'two', :msg => 'value "%2$s" incorrect for %1$s', :proc => flunker
236
+ end
237
+ end
238
+ assert !form.validate
239
+ assert_equal 'een: advies voor Resultaat-veld', form[:elem_a].errors[0].message
240
+ assert_equal 'twee: advies voor Resultaat-veld', form[:elem_a].errors[1].message
241
+ end
242
+
243
+ def test_errors_enumerable
244
+ flunker = lambda { |v| v.element.errors.add(v.message, v.code) }
245
+ form = ActiveForm::compose :form do |f|
246
+ f.text_element :elem_a, :label => 'A', :value => 'foo' do |e|
247
+ e.validates_with_proc :code => 'test-code', :proc => flunker
248
+ end
249
+ end
250
+ assert !form.validate
251
+ assert_equal ["A: validation failed"], form[:elem_a].errors.collect(&:msg)
252
+ assert_equal ['test-code'], form[:elem_a].errors.collect(&:code)
253
+ assert_equal ["%s: validation failed"], form[:elem_a].validators_by_type('test-code').collect(&:message)
254
+ end
255
+
256
+ def test_validate_group
257
+ flunker = lambda { |v| v.element.errors.add(v.message, v.code) }
258
+ form = ActiveForm::compose :form do |f|
259
+ f.section :section do |s|
260
+ s.validates_with_proc :msg => '%s: cannot be blank' do |v|
261
+ v.element.each do |elem|
262
+ elem.errors.add(v.message, 'blank') if elem.blank?
263
+ # ... add more validations here if needed
264
+ end
265
+ end
266
+ s.text_element :elem_b, :label => 'B' do |e|
267
+ e.validates_with_proc :code => 'test-code', :proc => flunker
268
+ end
269
+ s.text_element :elem_c, :label => 'C'
270
+ end
271
+ end
272
+ form[:section].define_element_at_top :text, :elem_a, :label => 'A'
273
+ assert_equal ['A', 'B', 'C'], form[:section].collect(&:label)
274
+ assert !form.validate
275
+ assert_equal ["A: cannot be blank", "B: validation failed", "B: cannot be blank", "C: cannot be blank"], form.all_errors.collect(&:message)
276
+ assert_equal ["A: cannot be blank", "B: validation failed", "C: cannot be blank"], form.initial_errors.collect(&:message)
277
+ assert_equal form.all_errors, form[:section].all_errors
278
+ end
279
+
280
+ def test_each_error
281
+ flunker = lambda { |v| v.element.errors.add(v.message, v.code) }
282
+ form = ActiveForm::compose :form do |f|
283
+ f.text_element :elem_a, :label => 'A', :value => 'foo' do |e|
284
+ e.validates_with_proc :proc => flunker
285
+ end
286
+ f.section :section do |s|
287
+ s.text_element :elem_b, :label => 'B', :value => 'foo' do |e|
288
+ e.validates_with_proc :proc => flunker
289
+ e.validates_with_proc :proc => flunker, :msg => '%s failed'
290
+ end
291
+ end
292
+ end
293
+ assert !form.validate
294
+ expected = ['A: validation failed', 'B: validation failed', 'B failed']
295
+ check = []
296
+ form.each_error { |e| check << e.message }
297
+ assert_equal expected, check
298
+ assert_equal 3, check.length
299
+ expected = ['A: validation failed']
300
+ check = []
301
+ form[:elem_a].each_error { |e| check << e.message }
302
+ assert_equal expected, check
303
+ assert_equal 1, check.length
304
+ expected = ['B: validation failed', 'B failed']
305
+ check = []
306
+ form[:section].each_error { |e| check << e.message }
307
+ assert_equal expected, check
308
+ assert_equal 2, check.length
309
+ end
310
+
311
+ def test_every_error
312
+ flunker = lambda { |v| v.element.errors.add(v.message, v.code) }
313
+ form = ActiveForm::compose :form do |f|
314
+ f.text_element :elem_a, :label => 'A', :value => 'foo' do |e|
315
+ e.validates_with_proc :proc => flunker
316
+ end
317
+ f.section :section do |s|
318
+ s.text_element :elem_b, :label => 'B', :value => 'foo' do |e|
319
+ e.validates_with_proc :proc => flunker
320
+ e.validates_with_proc :proc => flunker, :msg => '%s failed'
321
+ end
322
+ end
323
+ end
324
+ assert !form.validate
325
+ expected = ['A: validation failed', 'B: validation failed']
326
+ check = []
327
+ form.every_error { |e| check << e.message }
328
+ assert_equal expected, check
329
+ assert_equal 2, check.length
330
+ expected = ['A: validation failed']
331
+ check = []
332
+ form[:elem_a].every_error { |e| check << e.message }
333
+ assert_equal expected, check
334
+ assert_equal 1, check.length
335
+ expected = ['B: validation failed']
336
+ check = []
337
+ form[:section].every_error { |e| check << e.message }
338
+ assert_equal expected, check
339
+ assert_equal 1, check.length
340
+ end
341
+
342
+ def test_add_custom_javascript_validation
343
+ form = ActiveForm::compose :form, :client_side => true do |f|
344
+ f.javascript_validation do |elem, code, params|
345
+ params[:name] = 'custom'
346
+ params[:msg] = 'Not valid'
347
+ code << "return Validation.get('IsEmpty').test(v) || /^[a-zA-Z]+$/.test(v)"
348
+ end
349
+ f.text_element :elem_a, :label => 'A' do |e|
350
+ e.css_class << 'validate-custom'
351
+ end
352
+ f.text_element :elem_b, :label => 'B' do |e|
353
+ e.css_class << 'validate-custom'
354
+ end
355
+ end
356
+ expected = %`var fform_form=$('form');if(fform_form){
357
+ Validation.add('validate-custom', "Not valid", function (v) {
358
+ return Validation.get('IsEmpty').test(v) || /^[a-zA-Z]+$/.test(v)
359
+ });
360
+ new Validation(fform_form, {stopOnFirst:false, useTitles:true});
361
+ }`
362
+ assert_equal expected, form.element_javascript
363
+ assert form[:elem_a].css_class.include?('elem_text')
364
+ assert form[:elem_a].css_class.include?('validate-custom')
365
+ assert form[:elem_b].css_class.include?('elem_text')
366
+ assert form[:elem_b].css_class.include?('validate-custom')
367
+ end
368
+
369
+ def test_custom_javascript_element_validation
370
+ form = ActiveForm::compose :form, :client_side => true do |f|
371
+ f.text_element :elem_a, :label => 'A' do |e|
372
+ e.javascript_validation do |elem, code, params|
373
+ code << "return Validation.get('IsEmpty').test(v) || /^[a-zA-Z]+$/.test(v)"
374
+ end
375
+ end
376
+ f.text_element :elem_b, :label => 'B' do |e|
377
+ e.javascript_validation do |elem, code, params|
378
+ params[:name] = 'reusable'
379
+ params[:msg] = 'Not valid'
380
+ code << "return Validation.get('IsEmpty').test(v) || /^[a-zA-Z]+$/.test(v)"
381
+ end
382
+ end
383
+ end
384
+ expected = %`Validation.add('validate-form-elem-a', "A: validation failed", function (v) {
385
+ return Validation.get('IsEmpty').test(v) || /^[a-zA-Z]+$/.test(v)
386
+ });`
387
+ assert_equal expected, form[:elem_a].javascript_validation_code
388
+ expected = %`Validation.add('validate-reusable', "Not valid", function (v) {
389
+ return Validation.get('IsEmpty').test(v) || /^[a-zA-Z]+$/.test(v)
390
+ });`
391
+ assert_equal expected, form[:elem_b].javascript_validation_code
392
+ expected = %`var fform_form=$('form');if(fform_form){
393
+ var ftext_form_elem_a=$('form_elem_a');if(ftext_form_elem_a){
394
+ Validation.add('validate-form-elem-a', "A: validation failed", function (v) {
395
+ return Validation.get('IsEmpty').test(v) || /^[a-zA-Z]+$/.test(v)
396
+ });
397
+ }
398
+ var ftext_form_elem_b=$('form_elem_b');if(ftext_form_elem_b){
399
+ Validation.add('validate-reusable', "Not valid", function (v) {
400
+ return Validation.get('IsEmpty').test(v) || /^[a-zA-Z]+$/.test(v)
401
+ });
402
+ }
403
+ new Validation(fform_form, {stopOnFirst:false, useTitles:true});
404
+ }`
405
+ assert_equal expected, form.element_javascript
406
+ assert form[:elem_a].css_class.include?("validate-form-elem-a")
407
+ assert form[:elem_b].css_class.include?("validate-reusable")
408
+ end
409
+
410
+ def test_gather_validation_advice
411
+ form = ActiveForm::compose :form, :client_side => true do |f|
412
+ f.text_element :elem_a, :label => 'A' do |e|
413
+ e.validates_as_required
414
+ e.validates_as_number
415
+ end
416
+ f.text_element :elem_b, :label => 'B' do |e|
417
+ e.validates_as_required
418
+ e.validates_as_alpha
419
+ end
420
+ f.text_element :elem_c, :label => 'C' do |e|
421
+ e.validates_as_required
422
+ end
423
+ end
424
+ expected = %`var fform_form=$('form');if(fform_form){
425
+ new Validation(fform_form, {stopOnFirst:false, useTitles:true});
426
+ }`
427
+ assert_equal expected, form.element_javascript
428
+ assert form[:elem_a].css.include?('elem_text')
429
+ assert form[:elem_a].css.include?('required')
430
+ assert form[:elem_a].css.include?('validate-number')
431
+ assert form[:elem_b].css.include?('elem_text')
432
+ assert form[:elem_b].css.include?('required')
433
+ assert form[:elem_b].css.include?('validate-alpha')
434
+ assert form[:elem_c].css.include?('elem_text')
435
+ assert form[:elem_c].css.include?('required')
436
+
437
+ assert_equal ["A: can't be blank", "A: should be numeric"], form[:elem_a].gather_validation_advice.collect(&:message)
438
+ assert_equal ["B: can't be blank", "B: should contain alphabetical characters only"], form[:elem_b].gather_validation_advice.collect(&:message)
439
+ assert_equal ["C: can't be blank"], form[:elem_c].gather_validation_advice.collect(&:message)
440
+
441
+ expected = [ ["form_elem_a", "A: can't be blank"], ["form_elem_a", "A: should be numeric"],
442
+ ["form_elem_b", "B: can't be blank"], ["form_elem_b", "B: should contain alphabetical characters only"],
443
+ ["form_elem_c", "C: can't be blank"]
444
+ ]
445
+ assert_equal expected, form.gather_validation_advice.collect { |adv| [adv.element.identifier, adv.message] }
446
+
447
+ assert !form.validate
448
+ params = { :form => { :elem_a => '123', :elem_b => 'abcde', :elem_c => 'fghi' } }
449
+ form.update_from_params(params)
450
+ assert form.validate
451
+ end
452
+
453
+ def test_gather_nested_elements_validation_advice
454
+ form = ActiveForm::compose :form, :client_side => true do |f|
455
+ f.text_element :elem_a, :label => 'A' do |e|
456
+ e.validates_as_required
457
+ e.validates_as_number
458
+ end
459
+ f.section :section do |s|
460
+ s.text_element :elem_b, :label => 'B' do |e|
461
+ e.validates_as_required
462
+ e.validates_as_alpha
463
+ end
464
+ s.text_element :elem_c, :label => 'C' do |e|
465
+ e.validates_as_required
466
+ end
467
+ end
468
+ end
469
+ assert form[:elem_a].css.include?('elem_text')
470
+ assert form[:elem_a].css.include?('required')
471
+ assert form[:elem_a].css.include?('validate-number')
472
+ assert form[:section][:elem_b].css.include?('elem_text')
473
+ assert form[:section][:elem_b].css.include?('required')
474
+ assert form[:section][:elem_b].css.include?('validate-alpha')
475
+ assert form[:section][:elem_c].css.include?('elem_text')
476
+ assert form[:section][:elem_c].css.include?('required')
477
+
478
+ assert_equal ["A: can't be blank", "A: should be numeric"], form[:elem_a].gather_validation_advice.collect(&:message)
479
+ assert_equal ["B: can't be blank", "B: should contain alphabetical characters only"], form[:section][:elem_b].gather_validation_advice.collect(&:message)
480
+ assert_equal ["C: can't be blank"], form[:section][:elem_c].gather_validation_advice.collect(&:message)
481
+
482
+ expected = [ ["form_elem_a", "A: can't be blank"], ["form_elem_a", "A: should be numeric"],
483
+ ["form_section_elem_b", "B: can't be blank"], ["form_section_elem_b", "B: should contain alphabetical characters only"],
484
+ ["form_section_elem_c", "C: can't be blank"]
485
+ ]
486
+ assert_equal expected, form.gather_validation_advice.collect { |adv| [adv.element.identifier, adv.message] }
487
+ end
488
+
489
+ def test_validation_css_class
490
+ form = ActiveForm::compose :form, :client_side => true do |f|
491
+ f.text_element :elem_a, :label => 'A', :required => true do |e|
492
+ e.validates_as_number
493
+ end
494
+ end
495
+ assert_equal ["required", "validate-number"], form[:elem_a].validation_css_class
496
+ assert_equal ["required", "validate-number"], form[:elem_a].runtime_css_class
497
+ end
498
+
499
+ def test_server_side_validation_advice
500
+ form = ActiveForm::compose :form do |f|
501
+ f.text_element :elem_a, :label => 'A' do |e|
502
+ e.validates_as_required
503
+ e.validates_as_number
504
+ end
505
+ f.text_element :elem_b, :label => 'B' do |e|
506
+ e.validates_as_required
507
+ e.validates_as_alpha
508
+ end
509
+ end
510
+ assert_equal '', form[:elem_a].server_side_validation_advice
511
+ assert_equal '', form[:elem_b].server_side_validation_advice
512
+ assert !form.validate
513
+ expected = %`<div class="validation-advice advice-required" id="advice-required-form_elem_a">A: can't be blank</div>\n`
514
+ assert_equal expected, form[:elem_a].server_side_validation_advice
515
+ expected = %`<div class="validation-advice advice-required" id="advice-required-form_elem_b">B: can't be blank</div>\n`
516
+ assert_equal expected, form[:elem_b].server_side_validation_advice
517
+ expected = %`<div class="validation-advice advice-required" id="advice-required-form_elem_a">A: can't be blank</div>
518
+ <div class="validation-advice advice-required" id="advice-required-form_elem_b">B: can't be blank</div>\n`
519
+ assert_equal expected, form.server_side_validation_advice
520
+ expected = %`<div class="validation-advice advice-required" id="advice-required-form_elem_a">A: can't be blank</div>
521
+ <div class="validation-advice advice-required" id="advice-required-form_elem_b">B: can't be blank</div>\n`
522
+ assert_equal expected, form.all_server_side_validation_advice
523
+ end
524
+
525
+ def test_client_side_validation_advice
526
+ form = ActiveForm::compose :form, :client_side => true do |f|
527
+ f.text_element :elem_a, :label => 'A' do |e|
528
+ e.validates_as_required
529
+ e.validates_as_number
530
+ end
531
+ f.text_element :elem_b, :label => 'B' do |e|
532
+ e.validates_as_required
533
+ e.validates_as_alpha
534
+ end
535
+ end
536
+ expected = %`<div class="validation-advice advice-required" id="advice-required-form_elem_a" style="display: none">A: can't be blank</div>
537
+ <div class="validation-advice advice-number" id="advice-validate-number-form_elem_a" style="display: none">A: should be numeric</div>\n`
538
+ assert_equal expected, form[:elem_a].client_side_validation_advice
539
+ expected = %`<div class="validation-advice advice-required" id="advice-required-form_elem_b" style="display: none">B: can't be blank</div>
540
+ <div class="validation-advice advice-alpha" id="advice-validate-alpha-form_elem_b" style="display: none">B: should contain alphabetical characters only</div>\n`
541
+ assert_equal expected, form[:elem_b].client_side_validation_advice
542
+ expected = %`<div class="validation-advice advice-required" id="advice-required-form_elem_a" style="display: none">A: can't be blank</div>
543
+ <div class="validation-advice advice-number" id="advice-validate-number-form_elem_a" style="display: none">A: should be numeric</div>
544
+ <div class="validation-advice advice-required" id="advice-required-form_elem_b" style="display: none">B: can't be blank</div>
545
+ <div class="validation-advice advice-alpha" id="advice-validate-alpha-form_elem_b" style="display: none">B: should contain alphabetical characters only</div>\n`
546
+ assert_equal expected, form.client_side_validation_advice
547
+ end
548
+
549
+ def test_validation_advice
550
+ form = ActiveForm::compose :form, :client_side => true do |f|
551
+ f.text_element :elem_a, :label => 'A' do |e|
552
+ e.validates_as_required :msg => '%s: should not be left blank'
553
+ e.validates_as_number :msg => '%s: numeric values only'
554
+ end
555
+ f.text_element :elem_b, :label => 'B' do |e|
556
+ e.validates_as_required :msg => '%s: should not be left blank'
557
+ e.validates_as_alpha :msg => '%s: letter characters only please'
558
+ end
559
+ end
560
+ expected = %`<div class="validation-advice advice-required" id="advice-required-form_elem_a" style="display: none">A: should not be left blank</div>
561
+ <div class="validation-advice advice-number" id="advice-validate-number-form_elem_a" style="display: none">A: numeric values only</div>
562
+ <div class="validation-advice advice-required" id="advice-required-form_elem_b" style="display: none">B: should not be left blank</div>
563
+ <div class="validation-advice advice-alpha" id="advice-validate-alpha-form_elem_b" style="display: none">B: letter characters only please</div>\n`
564
+ assert_equal expected, form.validation_advice
565
+ end
566
+
567
+ def test_localized_validation_advice
568
+ translations = {
569
+ 'form_elem_a_label' => 'Foo',
570
+ 'form_elem_a_validates_required' => '%s: mag niet leeg zijn',
571
+ 'form_elem_a_validates_number' => '%s: dit moet een nummer zijn',
572
+ 'form_elem_b_label' => 'Bar',
573
+ 'form_elem_b_validates_required' => '%s: mag niet leeg zijn',
574
+ 'form_elem_b_validates_alpha' => '%s: mag alleen letters bevatten'
575
+ }
576
+ form = ActiveForm::compose :form, :client_side => true do |f|
577
+ f.define_localizer { |formname, elemname, key| translations[ [formname, elemname, key].compact.join('_') ] }
578
+ f.text_element :elem_a, :label => 'A' do |e|
579
+ e.validates_as_required
580
+ e.validates_as_number
581
+ end
582
+ f.text_element :elem_b, :label => 'B' do |e|
583
+ e.validates_as_required
584
+ e.validates_as_alpha
585
+ end
586
+ end
587
+ expected = %`<div class="validation-advice advice-required" id="advice-required-form_elem_a" style="display: none">Foo: mag niet leeg zijn</div>
588
+ <div class="validation-advice advice-number" id="advice-validate-number-form_elem_a" style="display: none">Foo: dit moet een nummer zijn</div>
589
+ <div class="validation-advice advice-required" id="advice-required-form_elem_b" style="display: none">Bar: mag niet leeg zijn</div>
590
+ <div class="validation-advice advice-alpha" id="advice-validate-alpha-form_elem_b" style="display: none">Bar: mag alleen letters bevatten</div>\n`
591
+ assert_equal expected, form.validation_advice
592
+ end
593
+
594
+ def test_javascript_validator_definition
595
+ form = ActiveForm::compose :form, :client_side => true do |f|
596
+ f.text_element :elem_a, :label => 'A' do |e|
597
+ e.validates_as_sample
598
+ end
599
+ f.submit_element :label => 'Validate'
600
+ end
601
+ assert form[:elem_a].css.include?('validate-sample')
602
+ expected = %`Validation.add('validate-sample', "value needs to be identical to 'sample'", function (v) {
603
+ return Validation.get('IsEmpty').test(v) || /^sample$/i.test(v);
604
+ });`
605
+ assert_equal expected, form.validation_javascript_definitions
606
+ expected = %`var fform_form=$('form');if(fform_form){
607
+ Validation.add('validate-sample', "value needs to be identical to 'sample'", function (v) {
608
+ return Validation.get('IsEmpty').test(v) || /^sample$/i.test(v);
609
+ });
610
+ new Validation(fform_form, {stopOnFirst:false, useTitles:true});
611
+ }`
612
+ assert_equal expected, form.js
613
+ assert_equal ["sample"], form[:elem_a].validators.collect(&:code)
614
+ end
615
+
616
+ def test_validates_as_required_alternative
617
+ form = ActiveForm::compose :form do |f|
618
+ f.text_element :elem_a, :required => true
619
+ end
620
+ assert form[:elem_a].css.include?('required')
621
+ assert_equal ["required"], form[:elem_a].validators.collect(&:code)
622
+ form[:elem_a].required = false
623
+ assert_equal [], form[:elem_a].validators.collect(&:code)
624
+ end
625
+
626
+ def test_mixed_validations
627
+ is_blank = lambda { |v| v.element.errors.add(v.message, v.code) if v.value.blank? }
628
+ form = ActiveForm::compose :form, :client_side => true do |f|
629
+ f.text_element :elem_a, :label => 'A' do |e|
630
+ e.validates_as_required
631
+ e.validates_as_number
632
+ e.validates_with_proc :code => 'test-code', :proc => is_blank, :msg => '%s: is_blank proc validation failed'
633
+ e.define_validation { |elem| elem.errors.add('%s is empty', 'empty') if elem.blank? }
634
+ end
635
+ end
636
+ expected = ["A: can't be blank", "A: should be numeric"]
637
+ assert_equal expected, form.gather_validation_advice.collect(&:message)
638
+ assert !form.validate
639
+ expected = ["A: can't be blank", "A: is_blank proc validation failed", "A is empty"]
640
+ assert_equal expected, form.all_errors.collect(&:message)
641
+ form[:elem_a].value = '1234'
642
+ assert form.validate
643
+ end
644
+
645
+ def test_after_validation_callback
646
+ ActiveForm::Element::Base.define_element_wrapper do |builder, elem, render|
647
+ builder.div(:id => "elem_#{elem.identifier}", :class => elem.css, :style => elem.style) do
648
+ elem.frozen? ? builder.span(elem.label, elem.label_attributes) : elem.render_label(builder)
649
+ builder.br
650
+ render.call
651
+ end
652
+ end
653
+
654
+ form = ActiveForm::compose :myform do |f|
655
+ f.text_element :first_name, :required => true
656
+ f.text_element :last_name, :required => true do |e|
657
+ e.after_validation do |elem|
658
+ elem.value += ' (OK)' if elem.valid?
659
+ end
660
+ end
661
+ f.password_element :password, :required => true
662
+ f.password_element :password_confirm, :required => true
663
+ f.after_validation do |elem|
664
+ if elem.valid?
665
+ elem.remove_elements(:password, :password_confirm)
666
+ elem.freeze!
667
+ end
668
+ end
669
+ end
670
+ assert !form.validate
671
+ expected = %`<!--o---------------------------[ myform ]---------------------------o-->
672
+ <div class="validation-advice advice-required" id="advice-required-myform_first_name">First Name: can't be blank</div>
673
+ <div class="validation-advice advice-required" id="advice-required-myform_last_name">Last Name: can't be blank</div>
674
+ <div class="validation-advice advice-required" id="advice-required-myform_password">Password: can't be blank</div>
675
+ <div class="validation-advice advice-required" id="advice-required-myform_password_confirm">Password Confirm: can't be blank</div>
676
+ <form action="#myform" class="active_form validation-failed" id="myform" method="post">
677
+ <div class="elem_text required validation-failed" id="elem_myform_first_name">
678
+ <label class="required validation-failed" for="myform_first_name">First Name</label>
679
+ <br/>
680
+ <input class="required" id="myform_first_name" name="myform[first_name]" size="30" type="text"/>
681
+ </div>
682
+ <div class="elem_text required validation-failed" id="elem_myform_last_name">
683
+ <label class="required validation-failed" for="myform_last_name">Last Name</label>
684
+ <br/>
685
+ <input class="required" id="myform_last_name" name="myform[last_name]" size="30" type="text"/>
686
+ </div>
687
+ <div class="elem_password required validation-failed" id="elem_myform_password">
688
+ <label class="required validation-failed" for="myform_password">Password</label>
689
+ <br/>
690
+ <input class="required" id="myform_password" name="myform[password]" size="30" type="password"/>
691
+ </div>
692
+ <div class="elem_password required validation-failed" id="elem_myform_password_confirm">
693
+ <label class="required validation-failed" for="myform_password_confirm">Password Confirm</label>
694
+ <br/>
695
+ <input class="required" id="myform_password_confirm" name="myform[password_confirm]" size="30" type="password"/>
696
+ </div>
697
+ </form>
698
+ <!--x---------------------------[ myform ]---------------------------x-->\n`
699
+ assert_equal expected, form.render
700
+ form.values[:first_name] = 'Fabien'
701
+ form.values[:last_name] = 'Franzen'
702
+ form.values[:password] = form.values[:password_confirm] = 'secret'
703
+ assert form.validate
704
+ assert_equal 'Franzen (OK)', form[:last_name].value
705
+
706
+ expected = %`<!--o---------------------------[ myform ]---------------------------o-->
707
+ <form action="#myform" class="active_form frozen" id="myform" method="post">
708
+ <div class="elem_text frozen required" id="elem_myform_first_name">
709
+ <span class="inactive required" for="myform_first_name">First Name</span>
710
+ <br/>
711
+ Fabien </div>
712
+ <div class="elem_text frozen required" id="elem_myform_last_name">
713
+ <span class="inactive required" for="myform_last_name">Last Name</span>
714
+ <br/>
715
+ Franzen (OK) </div>
716
+ </form>
717
+ <!--x---------------------------[ myform ]---------------------------x-->\n`
718
+ assert_equal expected, form.render
719
+ ActiveForm::Element::Base.reset_element_wrapper
720
+ end
721
+
722
+ end