comfy_bootstrap_form 4.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +621 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/stylesheets/rails_bootstrap_forms.css +10 -0
  6. data/lib/bootstrap_form.rb +13 -0
  7. data/lib/bootstrap_form/aliasing.rb +35 -0
  8. data/lib/bootstrap_form/form_builder.rb +460 -0
  9. data/lib/bootstrap_form/helper.rb +36 -0
  10. data/lib/bootstrap_form/helpers/bootstrap.rb +94 -0
  11. data/lib/bootstrap_form/helpers/nested_form.rb +33 -0
  12. data/lib/bootstrap_form/version.rb +3 -0
  13. data/lib/comfy_bootstrap_form.rb +1 -0
  14. data/test/bootstrap_checkbox_test.rb +144 -0
  15. data/test/bootstrap_fields_test.rb +152 -0
  16. data/test/bootstrap_form_group_test.rb +313 -0
  17. data/test/bootstrap_form_test.rb +276 -0
  18. data/test/bootstrap_other_components_test.rb +86 -0
  19. data/test/bootstrap_radio_button_test.rb +124 -0
  20. data/test/bootstrap_selects_test.rb +160 -0
  21. data/test/dummy/Gemfile +45 -0
  22. data/test/dummy/Gemfile.lock +120 -0
  23. data/test/dummy/README.rdoc +28 -0
  24. data/test/dummy/Rakefile +10 -0
  25. data/test/dummy/app/assets/javascripts/application.js +16 -0
  26. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  27. data/test/dummy/app/controllers/application_controller.rb +5 -0
  28. data/test/dummy/app/helpers/application_helper.rb +2 -0
  29. data/test/dummy/app/models/address.rb +3 -0
  30. data/test/dummy/app/models/faux_user.rb +9 -0
  31. data/test/dummy/app/models/super_user.rb +2 -0
  32. data/test/dummy/app/models/user.rb +9 -0
  33. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  34. data/test/dummy/bin/bundle +3 -0
  35. data/test/dummy/bin/rails +4 -0
  36. data/test/dummy/bin/rake +4 -0
  37. data/test/dummy/config.ru +4 -0
  38. data/test/dummy/config/application.rb +23 -0
  39. data/test/dummy/config/boot.rb +4 -0
  40. data/test/dummy/config/database.yml +25 -0
  41. data/test/dummy/config/environment.rb +5 -0
  42. data/test/dummy/config/environments/development.rb +29 -0
  43. data/test/dummy/config/environments/production.rb +80 -0
  44. data/test/dummy/config/environments/test.rb +53 -0
  45. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  46. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  47. data/test/dummy/config/initializers/generic_migration.rb +6 -0
  48. data/test/dummy/config/initializers/inflections.rb +16 -0
  49. data/test/dummy/config/initializers/mime_types.rb +5 -0
  50. data/test/dummy/config/initializers/secret_token.rb +12 -0
  51. data/test/dummy/config/initializers/session_store.rb +3 -0
  52. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  53. data/test/dummy/config/locales/en.yml +23 -0
  54. data/test/dummy/config/routes.rb +3 -0
  55. data/test/dummy/db/migrate/20130703191909_create_users.rb +13 -0
  56. data/test/dummy/db/migrate/20130703191937_create_addresses.rb +13 -0
  57. data/test/dummy/db/migrate/20130912171202_add_preferences_to_user.rb +5 -0
  58. data/test/dummy/db/migrate/20140327190145_add_terms_to_user.rb +5 -0
  59. data/test/dummy/db/migrate/20140922133133_add_type_to_users.rb +5 -0
  60. data/test/dummy/db/schema.rb +38 -0
  61. data/test/dummy/db/seeds.rb +7 -0
  62. data/test/dummy/db/test.sqlite3 +0 -0
  63. data/test/dummy/log/test.log +18394 -0
  64. data/test/dummy/public/404.html +58 -0
  65. data/test/dummy/public/422.html +58 -0
  66. data/test/dummy/public/500.html +57 -0
  67. data/test/dummy/public/favicon.ico +0 -0
  68. data/test/dummy/public/robots.txt +5 -0
  69. data/test/dummy/test/fixtures/addresses.yml +15 -0
  70. data/test/dummy/test/fixtures/users.yml +15 -0
  71. data/test/dummy/test/models/address_test.rb +7 -0
  72. data/test/dummy/test/models/user_test.rb +7 -0
  73. data/test/dummy/test/test_helper.rb +15 -0
  74. data/test/special_form_class_models_test.rb +43 -0
  75. data/test/test_helper.rb +86 -0
  76. metadata +309 -0
@@ -0,0 +1,313 @@
1
+ require 'test_helper'
2
+
3
+ class BootstrapFormGroupTest < ActionView::TestCase
4
+ include BootstrapForm::Helper
5
+
6
+ def setup
7
+ setup_test_fixture
8
+ end
9
+
10
+ test "changing the label text via the label option parameter" do
11
+ expected = %{<div class="form-group"><label class="form-control-label required" for="user_email">Email Address</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
12
+ assert_equivalent_xml expected, @builder.text_field(:email, label: 'Email Address')
13
+ end
14
+
15
+ test "changing the label text via the html_options label hash" do
16
+ expected = %{<div class="form-group"><label class="form-control-label required" for="user_email">Email Address</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
17
+ assert_equivalent_xml expected, @builder.text_field(:email, label: {text: 'Email Address'})
18
+ end
19
+
20
+ test "hiding a label" do
21
+ expected = %{<div class="form-group"><label class="sr-only form-control-label required" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
22
+ assert_equivalent_xml expected, @builder.text_field(:email, hide_label: true)
23
+ end
24
+
25
+ test "adding a custom label class via the label_class parameter" do
26
+ expected = %{<div class="form-group"><label class="btn form-control-label required" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
27
+ assert_equivalent_xml expected, @builder.text_field(:email, label_class: 'btn')
28
+ end
29
+
30
+ test "adding a custom label class via the html_options label hash" do
31
+ expected = %{<div class="form-group"><label class="btn form-control-label required" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
32
+ assert_equivalent_xml expected, @builder.text_field(:email, label: {class: 'btn'})
33
+ end
34
+
35
+ test "adding a custom label and changing the label text via the html_options label hash" do
36
+ expected = %{<div class="form-group"><label class="btn form-control-label required" for="user_email">Email Address</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
37
+ assert_equivalent_xml expected, @builder.text_field(:email, label: {class: 'btn', text: "Email Address"})
38
+ end
39
+
40
+ test "skipping a label" do
41
+ expected = %{<div class="form-group"><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
42
+ assert_equivalent_xml expected, @builder.text_field(:email, skip_label: true)
43
+ end
44
+
45
+ test "preventing a label from having the required class" do
46
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
47
+ assert_equivalent_xml expected, @builder.text_field(:email, skip_required: true)
48
+ end
49
+
50
+ test "adding prepend text" do
51
+ expected = %{<div class="form-group"><label class="form-control-label required" for="user_email">Email</label><div class="input-group"><span class="input-group-addon">@</span><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div></div>}
52
+ assert_equivalent_xml expected, @builder.text_field(:email, prepend: '@')
53
+ end
54
+
55
+ test "adding append text" do
56
+ expected = %{<div class="form-group"><label class="form-control-label required" for="user_email">Email</label><div class="input-group"><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /><span class="input-group-addon">.00</span></div></div>}
57
+ assert_equivalent_xml expected, @builder.text_field(:email, append: '.00')
58
+ end
59
+
60
+ test "append and prepend button" do
61
+ prefix = %{<div class="form-group"><label class="form-control-label required" for="user_email">Email</label><div class="input-group">}
62
+ field = %{<input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" />}
63
+ button = %{<span class="input-group-btn"><a class="btn btn-secondary" href="#">Click</a></span>}
64
+ suffix = %{</div></div>}
65
+ after_button = prefix + field + button + suffix
66
+ before_button = prefix + button + field + suffix
67
+ both_button = prefix + button + field + button + suffix
68
+ button_src = link_to("Click", "#", class: "btn btn-secondary")
69
+ assert_equivalent_xml after_button, @builder.text_field(:email, append: button_src)
70
+ assert_equivalent_xml before_button, @builder.text_field(:email, prepend: button_src)
71
+ assert_equivalent_xml both_button, @builder.text_field(:email, append: button_src, prepend: button_src)
72
+ end
73
+
74
+ test "adding both prepend and append text" do
75
+ expected = %{<div class="form-group"><label class="form-control-label required" for="user_email">Email</label><div class="input-group"><span class="input-group-addon">$</span><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /><span class="input-group-addon">.00</span></div></div>}
76
+ assert_equivalent_xml expected, @builder.text_field(:email, prepend: '$', append: '.00')
77
+ end
78
+
79
+ test "help messages for default forms" do
80
+ expected = %{<div class="form-group"><label class="form-control-label required" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /><span class="form-text text-muted">This is required</span></div>}
81
+ assert_equivalent_xml expected, @builder.text_field(:email, help: 'This is required')
82
+ end
83
+
84
+ test "help messages for horizontal forms" do
85
+ expected = %{<div class="form-group row"><label class="form-control-label col-sm-2 required" for="user_email">Email</label><div class="col-sm-10"><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /><span class="form-text text-muted">This is required</span></div></div>}
86
+ assert_equivalent_xml expected, @horizontal_builder.text_field(:email, help: "This is required")
87
+ end
88
+
89
+ test "help messages to look up I18n automatically" do
90
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_password">Password</label><input class="form-control" id="user_password" name="user[password]" type="text" value="secret" /><span class="form-text text-muted">A good password should be at least six characters long</span></div>}
91
+ assert_equivalent_xml expected, @builder.text_field(:password)
92
+ end
93
+
94
+ test "help messages to warn about deprecated I18n key" do
95
+ super_user = SuperUser.new(@user.attributes)
96
+ builder = BootstrapForm::FormBuilder.new(:super_user, super_user, self, {})
97
+
98
+ I18n.backend.store_translations(:en, activerecord: {
99
+ help: {
100
+ superuser: {
101
+ password: 'A good password should be at least six characters long'
102
+ }
103
+ }
104
+ })
105
+
106
+ builder.stubs(:warn).returns(true)
107
+ builder.expects(:warn).at_least_once
108
+
109
+ builder.password_field(:password)
110
+ end
111
+
112
+ test "help messages to ignore translation when user disables help" do
113
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_password">Password</label><input class="form-control" id="user_password" name="user[password]" type="text" value="secret" /></div>}
114
+ assert_equivalent_xml expected, @builder.text_field(:password, help: false)
115
+ end
116
+
117
+ test "form_group creates a valid structure and allows arbitrary html to be added via a block" do
118
+ output = @horizontal_builder.form_group :nil, label: { text: 'Foo' } do
119
+ %{<p class="form-control-static">Bar</p>}.html_safe
120
+ end
121
+
122
+ expected = %{<div class="form-group row"><label class="form-control-label col-sm-2" for="user_nil">Foo</label><div class="col-sm-10"><p class="form-control-static">Bar</p></div></div>}
123
+ assert_equivalent_xml expected, output
124
+ end
125
+
126
+ test "form_group adds a spacer when no label exists for a horizontal form" do
127
+ output = @horizontal_builder.form_group do
128
+ %{<p class="form-control-static">Bar</p>}.html_safe
129
+ end
130
+
131
+ expected = %{<div class="form-group row"><div class="col-sm-10 col-sm-offset-2"><p class="form-control-static">Bar</p></div></div>}
132
+ assert_equivalent_xml expected, output
133
+ end
134
+
135
+ test "form_group renders the label correctly" do
136
+ output = @horizontal_builder.form_group :email, label: { text: 'Custom Control' } do
137
+ %{<p class="form-control-static">Bar</p>}.html_safe
138
+ end
139
+
140
+ expected = %{<div class="form-group row"><label class="form-control-label col-sm-2 required" for="user_email">Custom Control</label><div class="col-sm-10"><p class="form-control-static">Bar</p></div></div>}
141
+ assert_equivalent_xml expected, output
142
+ end
143
+
144
+ test "form_group accepts class thorugh options hash" do
145
+ output = @horizontal_builder.form_group :email, class: "foo" do
146
+ %{<p class="form-control-static">Bar</p>}.html_safe
147
+ end
148
+
149
+ expected = %{<div class="form-group foo row"><div class="col-sm-10 col-sm-offset-2"><p class="form-control-static">Bar</p></div></div>}
150
+ assert_equivalent_xml expected, output
151
+ end
152
+
153
+ test "form_group accepts class thorugh options hash without needing a name" do
154
+ output = @horizontal_builder.form_group class: "foo" do
155
+ %{<p class="form-control-static">Bar</p>}.html_safe
156
+ end
157
+
158
+ expected = %{<div class="form-group foo row"><div class="col-sm-10 col-sm-offset-2"><p class="form-control-static">Bar</p></div></div>}
159
+ assert_equivalent_xml expected, output
160
+ end
161
+
162
+ test "form_group overrides the label's 'class' and 'for' attributes if others are passed" do
163
+ output = @horizontal_builder.form_group nil, label: { text: 'Custom Control', class: 'foo', for: 'bar' } do
164
+ %{<p class="form-control-static">Bar</p>}.html_safe
165
+ end
166
+
167
+ expected = %{<div class="form-group row"><label class="foo form-control-label col-sm-2" for="bar">Custom Control</label><div class="col-sm-10"><p class="form-control-static">Bar</p></div></div>}
168
+ assert_equivalent_xml expected, output
169
+ end
170
+
171
+ test 'form_group renders the "error" class and message corrrectly when object is invalid' do
172
+ @user.email = nil
173
+ @user.valid?
174
+
175
+ output = @builder.form_group :email do
176
+ %{<p class="form-control-static">Bar</p>}.html_safe
177
+ end
178
+
179
+ expected = <<-HTML.strip_heredoc
180
+ <div class="form-group has-danger">
181
+ <p class="form-control-static">Bar</p>
182
+ <span class="invalid-feedback">can&#39;t be blank, is too short (minimum is 5 characters)</span>
183
+ </div>
184
+ HTML
185
+ assert_equivalent_xml expected, output
186
+ end
187
+
188
+ test "adds class to wrapped form_group by a field" do
189
+ expected = %{<div class="form-group none-margin"><label class="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="search" /></div>}
190
+ assert_equivalent_xml expected, @builder.search_field(:misc, wrapper_class: 'none-margin')
191
+ end
192
+
193
+ test "adds class to wrapped form_group by a field with errors" do
194
+ @user.email = nil
195
+ @user.valid?
196
+
197
+ expected = <<-HTML.strip_heredoc
198
+ <div class="form-group none-margin has-danger">
199
+ <div class="field_with_errors">
200
+ <label class="form-control-label required" for="user_email">Email</label>
201
+ </div>
202
+ <div class="field_with_errors">
203
+ <input class="form-control is-invalid" id="user_email" name="user[email]" type="email" />
204
+ </div>
205
+ <span class="invalid-feedback">can&#39;t be blank, is too short (minimum is 5 characters)</span>
206
+ </div>
207
+ HTML
208
+ assert_equivalent_xml expected, @builder.email_field(:email, wrapper_class: 'none-margin')
209
+ end
210
+
211
+ test "adds class to wrapped form_group by a field with errors when bootstrap_form_for is used" do
212
+ @user.email = nil
213
+ @user.valid?
214
+
215
+ output = bootstrap_form_for(@user) do |f|
216
+ f.text_field(:email, help: 'This is required', wrapper_class: 'none-margin')
217
+ end
218
+
219
+ expected = <<-HTML.strip_heredoc
220
+ <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form">
221
+ <input name="utf8" type="hidden" value="&#x2713;" />
222
+ <div class="form-group none-margin has-danger">
223
+ <label class="form-control-label required" for="user_email">Email</label>
224
+ <input class="form-control is-invalid" id="user_email" name="user[email]" type="text" />
225
+ <span class="invalid-feedback">can&#39;t be blank, is too short (minimum is 5 characters)</span>
226
+ </div>
227
+ </form>
228
+ HTML
229
+ assert_equivalent_xml expected, output
230
+ end
231
+
232
+ test "adds offset for form_group without label" do
233
+ output = @horizontal_builder.form_group do
234
+ @horizontal_builder.submit
235
+ end
236
+
237
+ expected = %{<div class="form-group row"><div class="col-sm-10 col-sm-offset-2"><input class="btn btn-secondary" name="commit" type="submit" value="Create User" /></div></div>}
238
+ assert_equivalent_xml expected, output
239
+ end
240
+
241
+ test "adds offset for form_group without label but specific label_col" do
242
+ output = @horizontal_builder.form_group label_col: 'col-sm-5', control_col: 'col-sm-8' do
243
+ @horizontal_builder.submit
244
+ end
245
+
246
+ expected = %{<div class="form-group row"><div class="col-sm-8 col-sm-offset-5"><input class="btn btn-secondary" name="commit" type="submit" value="Create User" /></div></div>}
247
+ assert_equivalent_xml expected, output
248
+ end
249
+
250
+ test "adding an icon to a field" do
251
+ expected = %{<div class="form-group has-feedback"><label class="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="email" /><span class="glyphicon glyphicon-ok form-control-feedback"></span></div>}
252
+ assert_equivalent_xml expected, @builder.email_field(:misc, icon: 'ok')
253
+ end
254
+
255
+ test "single form_group call in horizontal form should not be smash design" do
256
+ output = ''
257
+ output = @horizontal_builder.form_group do
258
+ "Hallo"
259
+ end
260
+
261
+ output = output + @horizontal_builder.text_field(:email)
262
+
263
+ expected = %{<div class="form-group row"><div class="col-sm-10 col-sm-offset-2">Hallo</div></div><div class="form-group row"><label class="form-control-label col-sm-2 required" for="user_email">Email</label><div class="col-sm-10"><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div></div>}
264
+ assert_equivalent_xml expected, output
265
+ end
266
+
267
+ test "adds data-attributes (or any other options) to wrapper" do
268
+ expected = %{<div class="form-group" data-foo="bar"><label class="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="search" /></div>}
269
+ assert_equivalent_xml expected, @builder.search_field(:misc, wrapper: { data: { foo: 'bar' } })
270
+ end
271
+
272
+ test "passing options to a form control get passed through" do
273
+ expected = %{<div class="form-group"><label class="form-control-label required" for="user_email">Email</label><input autofocus="autofocus" class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
274
+ assert_equivalent_xml expected, @builder.text_field(:email, autofocus: true)
275
+ end
276
+
277
+ test "doesn't throw undefined method error when the content block returns nil" do
278
+ output = @builder.form_group :nil, label: { text: 'Foo' } do
279
+ nil
280
+ end
281
+
282
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_nil">Foo</label></div>}
283
+ assert_equivalent_xml expected, output
284
+ end
285
+
286
+ test "custom form group layout option" do
287
+ expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group"><label class="form-control-label required" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com" /></div></form>}
288
+ assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :horizontal) { |f| f.email_field :email, layout: :inline }
289
+ end
290
+
291
+ test "non-default column span on form is reflected in form_group" do
292
+ non_default_horizontal_builder = BootstrapForm::FormBuilder.new(:user, @user, self, { layout: :horizontal, label_col: "col-sm-3", control_col: "col-sm-9" })
293
+ output = non_default_horizontal_builder.form_group do
294
+ %{<p class="form-control-static">Bar</p>}.html_safe
295
+ end
296
+
297
+ expected = %{<div class="form-group row"><div class="col-sm-9 col-sm-offset-3"><p class="form-control-static">Bar</p></div></div>}
298
+ assert_equivalent_xml expected, output
299
+ end
300
+
301
+ test "non-default column span on form isn't mutated" do
302
+ frozen_horizontal_builder = BootstrapForm::FormBuilder.new(:user, @user, self, { layout: :horizontal, label_col: "col-sm-3".freeze, control_col: "col-sm-9".freeze })
303
+ output = frozen_horizontal_builder.form_group { 'test' }
304
+
305
+ expected = %{<div class="form-group row"><div class="col-sm-9 col-sm-offset-3">test</div></div>}
306
+ assert_equivalent_xml expected, output
307
+ end
308
+
309
+ test ":input_group_class should apply to input-group" do
310
+ expected = %{<div class="form-group"><label class="form-control-label required" for="user_email">Email</label><div class="input-group input-group-lg"><input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com" /><span class="input-group-btn"><input class="btn btn-primary" name="commit" type="submit" value="Subscribe" /></span></div></div>}
311
+ assert_equivalent_xml expected, @builder.email_field(:email, append: @builder.primary('Subscribe'), input_group_class: 'input-group-lg')
312
+ end
313
+ end
@@ -0,0 +1,276 @@
1
+ require 'test_helper'
2
+
3
+ class BootstrapFormTest < ActionView::TestCase
4
+ include BootstrapForm::Helper
5
+
6
+ def setup
7
+ setup_test_fixture
8
+ end
9
+
10
+ test "default-style forms" do
11
+ expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div></form>}
12
+ assert_equivalent_xml expected, bootstrap_form_for(@user) { |f| nil }
13
+ end
14
+
15
+ test "inline-style forms" do
16
+ expected = %{<form accept-charset="UTF-8" action="/users" class="form-inline" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div></form>}
17
+ assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :inline) { |f| nil }
18
+ end
19
+
20
+ test "horizontal-style forms" do
21
+ expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group row"><label class="form-control-label col-sm-2 required" for="user_email">Email</label><div class="col-sm-10"><input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com" /></div></div></form>}
22
+ assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :horizontal) { |f| f.email_field :email }
23
+ end
24
+
25
+ test "existing styles aren't clobbered when specifying a form style" do
26
+ expected = %{<form accept-charset="UTF-8" action="/users" class="my-style" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group row"><label class="form-control-label col-sm-2 required" for="user_email">Email</label><div class="col-sm-10"><input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com" /></div></div></form>}
27
+ assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :horizontal, html: { class: "my-style" }) { |f| f.email_field :email }
28
+ end
29
+
30
+ test "given role attribute should not be covered by default role attribute" do
31
+ expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="not-a-form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div></form>}
32
+ assert_equivalent_xml expected, bootstrap_form_for(@user, html: { role: 'not-a-form'}) {|f| nil}
33
+ end
34
+
35
+ test "bootstrap_form_tag acts like a form tag" do
36
+ expected = %{<form accept-charset="UTF-8" action="/users" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group"><label class="form-control-label" for="email">Your Email</label><input class="form-control" id="email" name="email" type="text" /></div></form>}
37
+ assert_equivalent_xml expected, bootstrap_form_tag(url: '/users') { |f| f.text_field :email, label: "Your Email" }
38
+ end
39
+
40
+ test "bootstrap_form_tag does not clobber custom options" do
41
+ expected = %{<form accept-charset="UTF-8" action="/users" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group"><label class="form-control-label" for="ID">Email</label><input class="form-control" id="ID" name="NAME" type="text" /></div></form>}
42
+ assert_equivalent_xml expected, bootstrap_form_tag(url: '/users') { |f| f.text_field :email, name: 'NAME', id: "ID" }
43
+ end
44
+
45
+ test "bootstrap_form_tag allows an empty name for checkboxes" do
46
+ checkbox = if ::Rails::VERSION::STRING >= '5.1'
47
+ %{<div class="form-check"><label class="form-check-label" for="misc"><input name="misc" type="hidden" value="0" /><input class="form-check-input" id="misc" name="misc" type="checkbox" value="1" /> Misc</label></div>}
48
+ else
49
+ %{<div class="form-check"><label class="form-check-label" for="_misc"><input name="[misc]" type="hidden" value="0" /><input class="form-check-input" id="_misc" name="[misc]" type="checkbox" value="1" /> Misc</label></div>}
50
+ end
51
+ hidden = if ::Rails::VERSION::STRING >= '4.2'
52
+ %{<input name="utf8" type="hidden" value="&#x2713;" />}
53
+ else
54
+ %{<div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div>}
55
+ end
56
+ expected = %{<form accept-charset="UTF-8" action="/users" method="post" role="form">#{hidden}#{checkbox}</form>}
57
+ assert_equivalent_xml expected, bootstrap_form_tag(url: '/users') { |f| f.check_box :misc }
58
+ end
59
+
60
+ test "errors display correctly and inline_errors are turned off by default when label_errors is true" do
61
+ @user.email = nil
62
+ @user.valid?
63
+
64
+ expected = <<-HTML.strip_heredoc
65
+ <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form">
66
+ <input name="utf8" type="hidden" value="&#x2713;" />
67
+ <div class="form-group has-danger">
68
+ <label class="form-control-label required" for="user_email">Email can&#39;t be blank, is too short (minimum is 5 characters)</label>
69
+ <input class="form-control is-invalid" id="user_email" name="user[email]" type="text" />
70
+ </div>
71
+ </form>
72
+ HTML
73
+ assert_equivalent_xml expected, bootstrap_form_for(@user, label_errors: true) { |f| f.text_field :email }
74
+ end
75
+
76
+ test "errors display correctly and inline_errors can also be on when label_errors is true" do
77
+ @user.email = nil
78
+ @user.valid?
79
+
80
+ expected = <<-HTML.strip_heredoc
81
+ <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form">
82
+ <input name="utf8" type="hidden" value="&#x2713;" />
83
+ <div class="form-group has-danger">
84
+ <label class="form-control-label required" for="user_email">Email can&#39;t be blank, is too short (minimum is 5 characters)</label>
85
+ <input class="form-control is-invalid" id="user_email" name="user[email]" type="text" />
86
+ <span class="invalid-feedback">can't be blank, is too short (minimum is 5 characters)</span>
87
+ </div>
88
+ </form>
89
+ HTML
90
+ assert_equivalent_xml expected, bootstrap_form_for(@user, label_errors: true, inline_errors: true) { |f| f.text_field :email }
91
+ end
92
+
93
+ test "label error messages use humanized attribute names" do
94
+ I18n.backend.store_translations(:en, {activerecord: {attributes: {user: {email: 'Your e-mail address'}}}})
95
+
96
+ @user.email = nil
97
+ @user.valid?
98
+
99
+ expected = <<-HTML.strip_heredoc
100
+ <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form">
101
+ <input name="utf8" type="hidden" value="&#x2713;" />
102
+ <div class="form-group has-danger">
103
+ <label class="form-control-label required" for="user_email">Your e-mail address can&#39;t be blank, is too short (minimum is 5 characters)</label>
104
+ <input class="form-control is-invalid" id="user_email" name="user[email]" type="text" />
105
+ <span class="invalid-feedback">can&#39;t be blank, is too short (minimum is 5 characters)</span>
106
+ </div>
107
+ </form>
108
+ HTML
109
+ assert_equivalent_xml expected, bootstrap_form_for(@user, label_errors: true, inline_errors: true) { |f| f.text_field :email }
110
+
111
+ I18n.backend.store_translations(:en, {activerecord: {attributes: {user: {email: nil}}}})
112
+ end
113
+
114
+ test "alert message is wrapped correctly" do
115
+ @user.email = nil
116
+ @user.valid?
117
+ expected = %{<div class="alert alert-danger"><p>Please fix the following errors:</p><ul class="rails-bootstrap-forms-error-summary"><li>Email can&#39;t be blank</li><li>Email is too short (minimum is 5 characters)</li><li>Terms must be accepted</li></ul></div>}
118
+ assert_equivalent_xml expected, @builder.alert_message('Please fix the following errors:')
119
+ end
120
+
121
+ test "changing the class name for the alert message" do
122
+ @user.email = nil
123
+ @user.valid?
124
+ expected = %{<div class="my-css-class"><p>Please fix the following errors:</p><ul class="rails-bootstrap-forms-error-summary"><li>Email can&#39;t be blank</li><li>Email is too short (minimum is 5 characters)</li><li>Terms must be accepted</li></ul></div>}
125
+ assert_equivalent_xml expected, @builder.alert_message('Please fix the following errors:', class: 'my-css-class')
126
+ end
127
+
128
+ test "alert_message contains the error summary when inline_errors are turned off" do
129
+ @user.email = nil
130
+ @user.valid?
131
+
132
+ output = bootstrap_form_for(@user, inline_errors: false) do |f|
133
+ f.alert_message('Please fix the following errors:')
134
+ end
135
+
136
+ expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="alert alert-danger"><p>Please fix the following errors:</p><ul class="rails-bootstrap-forms-error-summary"><li>Email can&#39;t be blank</li><li>Email is too short (minimum is 5 characters)</li><li>Terms must be accepted</li></ul></div></form>}
137
+ assert_equivalent_xml expected, output
138
+ end
139
+
140
+ test "alert_message allows the error_summary to be turned off" do
141
+ @user.email = nil
142
+ @user.valid?
143
+
144
+ output = bootstrap_form_for(@user, inline_errors: false) do |f|
145
+ f.alert_message('Please fix the following errors:', error_summary: false)
146
+ end
147
+
148
+ expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="alert alert-danger"><p>Please fix the following errors:</p></div></form>}
149
+ assert_equivalent_xml expected, output
150
+ end
151
+
152
+ test "alert_message allows the error_summary to be turned on with inline_errors also turned on" do
153
+ @user.email = nil
154
+ @user.valid?
155
+
156
+ output = bootstrap_form_for(@user, inline_errors: true) do |f|
157
+ f.alert_message('Please fix the following errors:', error_summary: true)
158
+ end
159
+
160
+ expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="alert alert-danger"><p>Please fix the following errors:</p><ul class="rails-bootstrap-forms-error-summary"><li>Email can&#39;t be blank</li><li>Email is too short (minimum is 5 characters)</li><li>Terms must be accepted</li></ul></div></form>}
161
+ assert_equivalent_xml expected, output
162
+ end
163
+
164
+ test "error_summary returns an unordered list of errors" do
165
+ @user.email = nil
166
+ @user.valid?
167
+
168
+ expected = %{<ul class="rails-bootstrap-forms-error-summary"><li>Email can&#39;t be blank</li><li>Email is too short (minimum is 5 characters)</li><li>Terms must be accepted</li></ul>}
169
+ assert_equivalent_xml expected, @builder.error_summary
170
+ end
171
+
172
+ test 'errors_on renders the errors for a specific attribute when invalid' do
173
+ @user.email = nil
174
+ @user.valid?
175
+
176
+ expected = %{<div class="alert alert-danger">Email can&#39;t be blank, Email is too short (minimum is 5 characters)</div>}
177
+ assert_equivalent_xml expected, @builder.errors_on(:email)
178
+ end
179
+
180
+ test "custom label width for horizontal forms" do
181
+ expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group row"><label class="form-control-label col-sm-1 required" for="user_email">Email</label><div class="col-sm-10"><input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com" /></div></div></form>}
182
+ assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :horizontal) { |f| f.email_field :email, label_col: 'col-sm-1' }
183
+ end
184
+
185
+ test "offset for form group without label respects label width for horizontal forms" do
186
+ expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group row"><div class="col-md-10 col-md-offset-2"><input class="btn btn-secondary" name="commit" type="submit" value="Create User" /></div></div></form>}
187
+ assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :horizontal, label_col: 'col-md-2', control_col: 'col-md-10') { |f| f.form_group { f.submit } }
188
+ end
189
+
190
+ test "custom input width for horizontal forms" do
191
+ expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group row"><label class="form-control-label col-sm-2 required" for="user_email">Email</label><div class="col-sm-5"><input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com" /></div></div></form>}
192
+ assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :horizontal) { |f| f.email_field :email, control_col: 'col-sm-5' }
193
+ end
194
+
195
+ test "the field contains the error and is not wrapped in div.field_with_errors when bootstrap_form_for is used" do
196
+ @user.email = nil
197
+ @user.valid?
198
+
199
+ output = bootstrap_form_for(@user) do |f|
200
+ f.text_field(:email, help: 'This is required')
201
+ end
202
+
203
+ expected = <<-HTML.strip_heredoc
204
+ <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form">
205
+ <input name="utf8" type="hidden" value="&#x2713;" />
206
+ <div class="form-group has-danger">
207
+ <label class="form-control-label required" for="user_email">Email</label>
208
+ <input class="form-control is-invalid" id="user_email" name="user[email]" type="text" />
209
+ <span class="invalid-feedback">can't be blank, is too short (minimum is 5 characters)</span>
210
+ </div>
211
+ </form>
212
+ HTML
213
+ assert_equivalent_xml expected, output
214
+ end
215
+
216
+ test "the field is wrapped with div.field_with_errors when form_for is used" do
217
+ @user.email = nil
218
+ @user.valid?
219
+
220
+ output = form_for(@user, builder: BootstrapForm::FormBuilder) do |f|
221
+ f.text_field(:email, help: 'This is required')
222
+ end
223
+
224
+ expected = <<-HTML.strip_heredoc
225
+ <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
226
+ <input name="utf8" type="hidden" value="&#x2713;" />
227
+ <div class="form-group has-danger">
228
+ <div class="field_with_errors">
229
+ <label class="form-control-label required" for="user_email">Email</label>
230
+ </div>
231
+ <div class="field_with_errors">
232
+ <input class="form-control is-invalid" id="user_email" name="user[email]" type="text" />
233
+ </div>
234
+ <span class="invalid-feedback">can&#39;t be blank, is too short (minimum is 5 characters)</span>
235
+ </div>
236
+ </form>
237
+ HTML
238
+ assert_equivalent_xml expected, output
239
+ end
240
+
241
+ test "help is preserved when inline_errors: false is passed to bootstrap_form_for" do
242
+ @user.email = nil
243
+ @user.valid?
244
+
245
+ output = bootstrap_form_for(@user, inline_errors: false) do |f|
246
+ f.text_field(:email, help: 'This is required')
247
+ end
248
+
249
+ expected = <<-HTML.strip_heredoc
250
+ <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form">
251
+ <input name="utf8" type="hidden" value="&#x2713;" />
252
+ <div class="form-group has-danger">
253
+ <label class="form-control-label required" for="user_email">Email</label>
254
+ <input class="form-control is-invalid" id="user_email" name="user[email]" type="text" />
255
+ <span class="form-text text-muted">This is required</span>
256
+ </div>
257
+ </form>
258
+ HTML
259
+ assert_equivalent_xml expected, output
260
+ end
261
+
262
+ test "allows the form object to be nil" do
263
+ builder = BootstrapForm::FormBuilder.new :other_model, nil, self, {}
264
+ expected = %{<div class="form-group"><label class="form-control-label" for="other_model_email">Email</label><input class="form-control" id="other_model_email" name="other_model[email]" type="text" /></div>}
265
+ assert_equivalent_xml expected, builder.text_field(:email)
266
+ end
267
+
268
+ test 'errors_on hide attribute name in message' do
269
+ @user.email = nil
270
+ @user.valid?
271
+
272
+ expected = %{<div class="alert alert-danger">can&#39;t be blank, is too short (minimum is 5 characters)</div>}
273
+
274
+ assert_equivalent_xml expected, @builder.errors_on(:email, hide_attribute_name: true)
275
+ end
276
+ end