simple_form 2.0.0 → 3.5.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.

Potentially problematic release.


This version of simple_form might be problematic. Click here for more details.

Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +97 -198
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +572 -296
  5. data/lib/generators/simple_form/install_generator.rb +17 -7
  6. data/lib/generators/simple_form/templates/README +3 -4
  7. data/lib/generators/simple_form/templates/_form.html.erb +1 -0
  8. data/lib/generators/simple_form/templates/_form.html.haml +1 -0
  9. data/lib/generators/simple_form/templates/config/initializers/{simple_form.rb.tt → simple_form.rb} +57 -63
  10. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +155 -0
  11. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +111 -0
  12. data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +14 -7
  13. data/lib/simple_form/action_view_extensions/builder.rb +5 -305
  14. data/lib/simple_form/action_view_extensions/form_helper.rb +18 -20
  15. data/lib/simple_form/components/errors.rb +30 -3
  16. data/lib/simple_form/components/hints.rb +10 -3
  17. data/lib/simple_form/components/html5.rb +17 -3
  18. data/lib/simple_form/components/label_input.rb +21 -2
  19. data/lib/simple_form/components/labels.rb +16 -11
  20. data/lib/simple_form/components/maxlength.rb +19 -12
  21. data/lib/simple_form/components/min_max.rb +4 -2
  22. data/lib/simple_form/components/minlength.rb +48 -0
  23. data/lib/simple_form/components/pattern.rb +5 -4
  24. data/lib/simple_form/components/placeholders.rb +3 -2
  25. data/lib/simple_form/components/readonly.rb +3 -2
  26. data/lib/simple_form/components.rb +15 -11
  27. data/lib/simple_form/error_notification.rb +4 -3
  28. data/lib/simple_form/form_builder.rb +283 -105
  29. data/lib/simple_form/helpers/autofocus.rb +1 -0
  30. data/lib/simple_form/helpers/disabled.rb +1 -0
  31. data/lib/simple_form/helpers/readonly.rb +1 -0
  32. data/lib/simple_form/helpers/required.rb +1 -0
  33. data/lib/simple_form/helpers/validators.rb +4 -3
  34. data/lib/simple_form/helpers.rb +7 -6
  35. data/lib/simple_form/i18n_cache.rb +1 -0
  36. data/lib/simple_form/inputs/base.rb +76 -23
  37. data/lib/simple_form/inputs/block_input.rb +3 -2
  38. data/lib/simple_form/inputs/boolean_input.rb +55 -16
  39. data/lib/simple_form/inputs/collection_check_boxes_input.rb +2 -1
  40. data/lib/simple_form/inputs/collection_input.rb +41 -18
  41. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +11 -19
  42. data/lib/simple_form/inputs/collection_select_input.rb +5 -2
  43. data/lib/simple_form/inputs/date_time_input.rb +23 -12
  44. data/lib/simple_form/inputs/file_input.rb +5 -2
  45. data/lib/simple_form/inputs/grouped_collection_select_input.rb +16 -3
  46. data/lib/simple_form/inputs/hidden_input.rb +5 -2
  47. data/lib/simple_form/inputs/numeric_input.rb +4 -8
  48. data/lib/simple_form/inputs/password_input.rb +6 -4
  49. data/lib/simple_form/inputs/priority_input.rb +5 -2
  50. data/lib/simple_form/inputs/range_input.rb +2 -1
  51. data/lib/simple_form/inputs/string_input.rb +6 -4
  52. data/lib/simple_form/inputs/text_input.rb +6 -3
  53. data/lib/simple_form/inputs.rb +20 -17
  54. data/lib/simple_form/map_type.rb +1 -0
  55. data/lib/simple_form/railtie.rb +15 -0
  56. data/lib/simple_form/tags.rb +69 -0
  57. data/lib/simple_form/version.rb +2 -1
  58. data/lib/simple_form/wrappers/builder.rb +12 -35
  59. data/lib/simple_form/wrappers/leaf.rb +29 -0
  60. data/lib/simple_form/wrappers/many.rb +12 -7
  61. data/lib/simple_form/wrappers/root.rb +7 -4
  62. data/lib/simple_form/wrappers/single.rb +12 -3
  63. data/lib/simple_form/wrappers.rb +3 -1
  64. data/lib/simple_form.rb +118 -63
  65. data/test/action_view_extensions/builder_test.rb +230 -164
  66. data/test/action_view_extensions/form_helper_test.rb +107 -39
  67. data/test/components/label_test.rb +105 -87
  68. data/test/form_builder/association_test.rb +131 -62
  69. data/test/form_builder/button_test.rb +15 -14
  70. data/test/form_builder/error_notification_test.rb +11 -10
  71. data/test/form_builder/error_test.rb +188 -34
  72. data/test/form_builder/general_test.rb +247 -102
  73. data/test/form_builder/hint_test.rb +59 -32
  74. data/test/form_builder/input_field_test.rb +138 -25
  75. data/test/form_builder/label_test.rb +84 -13
  76. data/test/form_builder/wrapper_test.rb +236 -33
  77. data/test/generators/simple_form_generator_test.rb +15 -4
  78. data/test/inputs/boolean_input_test.rb +147 -13
  79. data/test/inputs/collection_check_boxes_input_test.rb +166 -71
  80. data/test/inputs/collection_radio_buttons_input_test.rb +229 -113
  81. data/test/inputs/collection_select_input_test.rb +222 -85
  82. data/test/inputs/datetime_input_test.rb +134 -47
  83. data/test/inputs/disabled_test.rb +62 -21
  84. data/test/inputs/discovery_test.rb +70 -10
  85. data/test/inputs/file_input_test.rb +4 -3
  86. data/test/inputs/general_test.rb +90 -26
  87. data/test/inputs/grouped_collection_select_input_test.rb +88 -23
  88. data/test/inputs/hidden_input_test.rb +7 -5
  89. data/test/inputs/numeric_input_test.rb +56 -46
  90. data/test/inputs/priority_input_test.rb +31 -16
  91. data/test/inputs/readonly_test.rb +68 -27
  92. data/test/inputs/required_test.rb +63 -18
  93. data/test/inputs/string_input_test.rb +76 -51
  94. data/test/inputs/text_input_test.rb +21 -8
  95. data/test/simple_form_test.rb +9 -0
  96. data/test/support/discovery_inputs.rb +39 -2
  97. data/test/support/misc_helpers.rb +176 -20
  98. data/test/support/mock_controller.rb +13 -7
  99. data/test/support/models.rb +187 -71
  100. data/test/test_helper.rb +38 -39
  101. metadata +53 -39
  102. data/lib/simple_form/core_ext/hash.rb +0 -16
  103. data/test/support/mock_response.rb +0 -14
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  # Tests for f.hint
@@ -8,40 +9,56 @@ class HintTest < ActionView::TestCase
8
9
  end
9
10
  end
10
11
 
11
- test 'hint should not be generated by default' do
12
+ test 'hint does not be generated by default' do
12
13
  with_hint_for @user, :name
13
14
  assert_no_select 'span.hint'
14
15
  end
15
16
 
16
- test 'hint should be generated with optional text' do
17
- with_hint_for @user, :name, :hint => 'Use with care...'
17
+ test 'hint is generated with optional text' do
18
+ with_hint_for @user, :name, hint: 'Use with care...'
18
19
  assert_select 'span.hint', 'Use with care...'
19
20
  end
20
21
 
21
- test 'hint should not modify the options hash' do
22
- options = { :hint => 'Use with care...' }
22
+ test 'hint is generated with decorated object responsive to #to_model' do
23
+ with_hint_for @decorated_user, :name, hint: 'Use with care...'
24
+ assert_select 'span.hint', 'Use with care...'
25
+ end
26
+
27
+ test 'hint does not modify the options hash' do
28
+ options = { hint: 'Use with care...' }
23
29
  with_hint_for @user, :name, options
24
30
  assert_select 'span.hint', 'Use with care...'
25
- assert_equal({ :hint => 'Use with care...' }, options)
31
+ assert_equal({ hint: 'Use with care...' }, options)
26
32
  end
27
33
 
28
- test 'hint should be generated cleanly with optional text' do
29
- with_hint_for @user, :name, :hint => 'Use with care...', :hint_tag => :span
34
+ test 'hint is generated cleanly with optional text' do
35
+ with_hint_for @user, :name, hint: 'Use with care...', hint_tag: :span
30
36
  assert_no_select 'span.hint[hint]'
31
37
  assert_no_select 'span.hint[hint_tag]'
32
38
  assert_no_select 'span.hint[hint_html]'
33
39
  end
34
40
 
35
41
  test 'hint uses the current component tag set' do
36
- with_hint_for @user, :name, :hint => 'Use with care...', :hint_tag => :p
42
+ with_hint_for @user, :name, hint: 'Use with care...', hint_tag: :p
37
43
  assert_select 'p.hint', 'Use with care...'
38
44
  end
39
45
 
40
- test 'hint should be able to pass html options' do
41
- with_hint_for @user, :name, :hint => 'Yay!', :id => 'hint', :class => 'yay'
46
+ test 'hint is able to pass html options' do
47
+ with_hint_for @user, :name, hint: 'Yay!', id: 'hint', class: 'yay'
42
48
  assert_select 'span#hint.hint.yay'
43
49
  end
44
50
 
51
+ test 'hint is output as html_safe' do
52
+ with_hint_for @user, :name, hint: '<b>Bold</b> and not...'.html_safe
53
+ assert_select 'span.hint', 'Bold and not...'
54
+ assert_select 'span.hint b', 'Bold'
55
+ end
56
+
57
+ test 'builder escapes hint text' do
58
+ with_hint_for @user, :name, hint: '<script>alert(1337)</script>'
59
+ assert_no_select 'span.hint script'
60
+ end
61
+
45
62
  # Without attribute name
46
63
 
47
64
  test 'hint without attribute name' do
@@ -49,66 +66,76 @@ class HintTest < ActionView::TestCase
49
66
  assert_select 'span.hint', 'Hello World!'
50
67
  end
51
68
 
52
- test 'hint without attribute name should generate component tag with a clean HTML' do
69
+ test 'hint without attribute name generates component tag with a clean HTML' do
53
70
  with_hint_for @validating_user, 'Hello World!'
54
71
  assert_no_select 'span.hint[hint]'
55
72
  assert_no_select 'span.hint[hint_html]'
56
73
  end
57
74
 
58
75
  test 'hint without attribute name uses the current component tag set' do
59
- with_hint_for @user, 'Hello World!', :hint_tag => :p
76
+ with_hint_for @user, 'Hello World!', hint_tag: :p
60
77
  assert_no_select 'p.hint[hint]'
61
78
  assert_no_select 'p.hint[hint_html]'
62
79
  assert_no_select 'p.hint[hint_tag]'
63
80
  end
64
81
 
65
- test 'hint without attribute name should be able to pass html options' do
66
- with_hint_for @user, 'Yay', :id => 'hint', :class => 'yay'
82
+ test 'hint without attribute name is able to pass html options' do
83
+ with_hint_for @user, 'Yay', id: 'hint', class: 'yay'
67
84
  assert_select 'span#hint.hint.yay', 'Yay'
68
85
  end
69
86
 
70
87
  # I18n
71
88
 
72
- test 'hint should use i18n based on model, action, and attribute to lookup translation' do
73
- store_translations(:en, :simple_form => { :hints => { :user => {
74
- :edit => { :name => 'Content of this input will be truncated...' }
89
+ test 'hint uses i18n based on model, action, and attribute to lookup translation' do
90
+ store_translations(:en, simple_form: { hints: { user: {
91
+ edit: { name: 'Content of this input will be truncated...' }
75
92
  } } }) do
76
93
  with_hint_for @user, :name
77
94
  assert_select 'span.hint', 'Content of this input will be truncated...'
78
95
  end
79
96
  end
80
97
 
81
- test 'hint should use i18n with model and attribute to lookup translation' do
82
- store_translations(:en, :simple_form => { :hints => { :user => {
83
- :name => 'Content of this input will be capitalized...'
98
+ test 'hint uses i18n with model and attribute to lookup translation' do
99
+ store_translations(:en, simple_form: { hints: { user: {
100
+ name: 'Content of this input will be capitalized...'
84
101
  } } }) do
85
102
  with_hint_for @user, :name
86
103
  assert_select 'span.hint', 'Content of this input will be capitalized...'
87
104
  end
88
105
  end
89
106
 
90
- test 'hint should use i18n under defaults namespace to lookup translation' do
91
- store_translations(:en, :simple_form => {
92
- :hints => {:defaults => {:name => 'Content of this input will be downcased...' } }
107
+ test 'hint uses i18n under defaults namespace to lookup translation' do
108
+ store_translations(:en, simple_form: {
109
+ hints: { defaults: { name: 'Content of this input will be downcased...' } }
93
110
  }) do
94
111
  with_hint_for @user, :name
95
112
  assert_select 'span.hint', 'Content of this input will be downcased...'
96
113
  end
97
114
  end
98
115
 
99
- test 'hint should use i18n with lookup for association name' do
100
- store_translations(:en, :simple_form => { :hints => {
101
- :user => { :company => 'My company!' }
116
+ test 'hint uses i18n with lookup for association name' do
117
+ store_translations(:en, simple_form: { hints: {
118
+ user: { company: 'My company!' }
102
119
  } } ) do
103
- with_hint_for @user, :company_id, :as => :string, :reflection => Association.new(Company, :company, {})
120
+ with_hint_for @user, :company_id, as: :string, reflection: Association.new(Company, :company, {})
104
121
  assert_select 'span.hint', /My company!/
105
122
  end
106
123
  end
107
124
 
125
+ test 'hint outputs translations as html_safe' do
126
+ store_translations(:en, simple_form: { hints: { user: {
127
+ edit: { name: '<b>This is bold</b> and this is not...' }
128
+ } } }) do
129
+ with_hint_for @user, :name
130
+ assert_select 'span.hint', 'This is bold and this is not...'
131
+ end
132
+ end
133
+
134
+
108
135
  # No object
109
136
 
110
- test 'hint should generate properly when object is not present' do
111
- with_hint_for :project, :name, :hint => 'Test without object'
137
+ test 'hint generates properly when object is not present' do
138
+ with_hint_for :project, :name, hint: 'Test without object'
112
139
  assert_select 'span.hint', 'Test without object'
113
140
  end
114
141
 
@@ -116,8 +143,8 @@ class HintTest < ActionView::TestCase
116
143
 
117
144
  test 'hint with custom wrappers works' do
118
145
  swap_wrapper do
119
- with_hint_for @user, :name, :hint => "can't be blank"
120
- assert_select 'div.omg_hint', "can't be blank"
146
+ with_hint_for @user, :name, hint: "cannot be blank"
147
+ assert_select 'div.omg_hint', "cannot be blank"
121
148
  end
122
149
  end
123
150
  end
@@ -1,63 +1,176 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  # Tests for f.input_field
4
5
  class InputFieldTest < ActionView::TestCase
5
- test "builder input_field should only render the input tag, nothing else" do
6
- with_concat_form_for(@user) do |f|
7
- f.input_field :name
6
+ def with_input_field_for(object, *args)
7
+ with_concat_form_for(object) do |f|
8
+ f.input_field(*args)
8
9
  end
10
+ end
11
+
12
+ test "builder input_field only renders the input tag, nothing else" do
13
+ with_input_field_for @user, :name
14
+
9
15
  assert_select 'form > input.required.string'
10
16
  assert_no_select 'div.string'
11
17
  assert_no_select 'label'
12
18
  assert_no_select '.hint'
13
19
  end
14
20
 
15
- test 'builder input_field should allow overriding default input type' do
16
- with_concat_form_for(@user) do |f|
17
- f.input_field :name, :as => :text
18
- end
21
+ test 'builder input_field allows overriding default input type' do
22
+ with_input_field_for @user, :name, as: :text
19
23
 
20
24
  assert_no_select 'input#user_name'
21
25
  assert_select 'textarea#user_name.text'
22
26
  end
23
27
 
24
- test 'builder input_field should allow passing options to input tag' do
25
- with_concat_form_for(@user) do |f|
26
- f.input_field :name, :id => 'name_input', :class => 'name'
27
- end
28
+ test 'builder input_field generates input type based on column type' do
29
+ with_input_field_for @user, :age
28
30
 
29
- assert_select 'input.string.name#name_input'
31
+ assert_select 'input[type=number].integer#user_age'
30
32
  end
31
33
 
32
- test 'builder input_field should not modify the options hash' do
33
- options = { :id => 'name_input', :class => 'name' }
34
+ test 'builder input_field is able to disable any component' do
35
+ with_input_field_for @user, :age, html5: false
34
36
 
35
- with_concat_form_for(@user) do |f|
36
- f.input_field :name, options
37
- end
37
+ assert_no_select 'input[html5=false]#user_age'
38
+ assert_select 'input[type=text].integer#user_age'
39
+ end
40
+
41
+ test 'builder input_field allows passing options to input tag' do
42
+ with_input_field_for @user, :name, id: 'name_input', class: 'name'
38
43
 
39
44
  assert_select 'input.string.name#name_input'
40
- assert_equal({ :id => 'name_input', :class => 'name' }, options)
41
45
  end
42
46
 
47
+ test 'builder input_field does not modify the options hash' do
48
+ options = { id: 'name_input', class: 'name' }
49
+ with_input_field_for @user, :name, options
43
50
 
44
- test 'builder input_field should generate an input tag with a clean HTML' do
45
- with_concat_form_for(@user) do |f|
46
- f.input_field :name, :as => :integer, :class => 'name'
47
- end
51
+ assert_select 'input.string.name#name_input'
52
+ assert_equal({ id: 'name_input', class: 'name' }, options)
53
+ end
54
+
55
+
56
+ test 'builder input_field generates an input tag with a clean HTML' do
57
+ with_input_field_for @user, :name, as: :integer, class: 'name'
48
58
 
49
59
  assert_no_select 'input.integer[input_html]'
50
60
  assert_no_select 'input.integer[as]'
51
61
  end
52
62
 
53
- test 'builder collection input_field should generate input tag with a clean HTML' do
54
- with_concat_form_for(@user) do |f|
55
- f.input_field :status, :collection => ['Open', 'Closed'], :class => 'status', :label_method => :to_s, :value_method => :to_s
63
+ test 'builder input_field uses i18n to translate placeholder text' do
64
+ store_translations(:en, simple_form: { placeholders: { user: {
65
+ name: 'Name goes here'
66
+ } } }) do
67
+ with_input_field_for @user, :name
68
+
69
+ assert_select 'input.string[placeholder="Name goes here"]'
56
70
  end
71
+ end
72
+
73
+ test 'builder input_field uses min_max component' do
74
+ with_input_field_for @other_validating_user, :age, as: :integer
75
+
76
+ assert_select 'input[min="18"]'
77
+ end
78
+
79
+ test 'builder input_field does not use pattern component by default' do
80
+ with_input_field_for @other_validating_user, :country, as: :string
81
+
82
+ assert_no_select 'input[pattern="\w+"]'
83
+ end
84
+
85
+ test 'builder input_field infers pattern from attributes' do
86
+ with_input_field_for @other_validating_user, :country, as: :string, pattern: true
87
+
88
+ assert_select 'input[pattern="\w+"]'
89
+ end
90
+
91
+ test 'builder input_field accepts custom pattern' do
92
+ with_input_field_for @other_validating_user, :country, as: :string, pattern: '\d+'
93
+
94
+ assert_select 'input[pattern="\d+"]'
95
+ end
96
+
97
+ test 'builder input_field uses readonly component' do
98
+ with_input_field_for @other_validating_user, :age, as: :integer, readonly: true
99
+
100
+ assert_select 'input.integer.readonly[readonly]'
101
+ end
102
+
103
+ test 'builder input_field uses maxlength component' do
104
+ with_input_field_for @validating_user, :name, as: :string
105
+
106
+ assert_select 'input.string[maxlength="25"]'
107
+ end
108
+
109
+ test 'builder input_field uses minlength component' do
110
+ with_input_field_for @validating_user, :name, as: :string
111
+
112
+ assert_select 'input.string[minlength="5"]'
113
+ end
114
+
115
+ test 'builder collection input_field generates input tag with a clean HTML' do
116
+ with_input_field_for @user, :status, collection: %w[Open Closed],
117
+ class: 'status', label_method: :to_s, value_method: :to_s
57
118
 
58
119
  assert_no_select 'select.status[input_html]'
59
120
  assert_no_select 'select.status[collection]'
60
121
  assert_no_select 'select.status[label_method]'
61
122
  assert_no_select 'select.status[value_method]'
62
123
  end
124
+
125
+ test 'build input_field does not treat "boolean_style" as a HTML attribute' do
126
+ with_input_field_for @user, :active, boolean_style: :nested
127
+
128
+ assert_no_select 'input.boolean[boolean_style]'
129
+ end
130
+
131
+ test 'build input_field does not treat "prompt" as a HTML attribute' do
132
+ with_input_field_for @user, :attempts, collection: [1,2,3,4,5], prompt: :translate
133
+
134
+ assert_no_select 'select[prompt]'
135
+ end
136
+
137
+ test 'build input_field without pattern component use the pattern string' do
138
+ swap_wrapper :default, custom_wrapper_with_html5_components do
139
+ with_input_field_for @user, :name, pattern: '\w+'
140
+
141
+ assert_select 'input[pattern="\w+"]'
142
+ end
143
+ end
144
+
145
+ test 'build input_field without placeholder component use the placeholder string' do
146
+ swap_wrapper :default, custom_wrapper_with_html5_components do
147
+ with_input_field_for @user, :name, placeholder: 'Placeholder'
148
+
149
+ assert_select 'input[placeholder="Placeholder"]'
150
+ end
151
+ end
152
+
153
+ test 'build input_field without maxlength component use the maxlength string' do
154
+ swap_wrapper :default, custom_wrapper_with_html5_components do
155
+ with_input_field_for @user, :name, maxlength: 5
156
+
157
+ assert_select 'input[maxlength="5"]'
158
+ end
159
+ end
160
+
161
+ test 'build input_field without minlength component use the minlength string' do
162
+ swap_wrapper :default, custom_wrapper_with_html5_components do
163
+ with_input_field_for @user, :name, minlength: 5
164
+
165
+ assert_select 'input[minlength="5"]'
166
+ end
167
+ end
168
+
169
+ test 'build input_field without readonly component use the readonly string' do
170
+ swap_wrapper :default, custom_wrapper_with_html5_components do
171
+ with_input_field_for @user, :name, readonly: true
172
+
173
+ assert_select 'input[readonly="readonly"]'
174
+ end
175
+ end
63
176
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: UTF-8
2
3
  require 'test_helper'
3
4
 
@@ -8,47 +9,78 @@ class LabelTest < ActionView::TestCase
8
9
  end
9
10
  end
10
11
 
11
- test 'builder should generate a label for the attribute' do
12
+ test 'builder generates a label for the attribute' do
12
13
  with_label_for @user, :name
13
14
  assert_select 'label.string[for=user_name]', /Name/
14
15
  end
15
16
 
16
- test 'builder should generate a label componet tag with a clean HTML' do
17
+ test 'builder generates a label for the attribute with decorated object responsive to #to_model' do
18
+ with_label_for @decorated_user, :name
19
+ assert_select 'label.string[for=user_name]', /Name/
20
+ end
21
+
22
+ test 'builder generates a label for the boolean attrbiute' do
23
+ with_label_for @user, :name, as: :boolean
24
+ assert_select 'label.boolean[for=user_name]', /Name/
25
+ assert_no_select 'label[as=boolean]'
26
+ end
27
+
28
+ test 'builder generates a label component tag with a clean HTML' do
17
29
  with_label_for @user, :name
18
30
  assert_no_select 'label.string[label_html]'
19
31
  end
20
32
 
21
- test 'builder should add a required class to label if the attribute is required' do
33
+ test 'builder adds a required class to label if the attribute is required' do
22
34
  with_label_for @validating_user, :name
23
35
  assert_select 'label.string.required[for=validating_user_name]', /Name/
24
36
  end
25
37
 
26
- test 'builder should allow passing options to label tag' do
27
- with_label_for @user, :name, :label => 'My label', :id => 'name_label'
38
+ test 'builder adds a disabled class to label if the attribute is disabled' do
39
+ with_label_for @validating_user, :name, disabled: true
40
+ assert_select 'label.string.disabled[for=validating_user_name]', /Name/
41
+ end
42
+
43
+ test 'builder does not add a disabled class to label if the attribute is not disabled' do
44
+ with_label_for @validating_user, :name, disabled: false
45
+ assert_no_select 'label.string.disabled[for=validating_user_name]', /Name/
46
+ end
47
+
48
+ test 'builder escapes label text' do
49
+ with_label_for @user, :name, label: '<script>alert(1337)</script>', required: false
50
+ assert_no_select 'label.string script'
51
+ end
52
+
53
+ test 'builder does not escape label text if it is safe' do
54
+ with_label_for @user, :name, label: '<script>alert(1337)</script>'.html_safe, required: false
55
+ assert_select 'label.string script', "alert(1337)"
56
+ end
57
+
58
+ test 'builder allows passing options to label tag' do
59
+ with_label_for @user, :name, label: 'My label', id: 'name_label'
28
60
  assert_select 'label.string#name_label', /My label/
29
61
  end
30
62
 
31
- test 'builder label should generate label tag with clean HTML' do
32
- with_label_for @user, :name, :label => 'My label', :required => true, :id => 'name_label'
63
+ test 'builder label generates label tag with clean HTML' do
64
+ with_label_for @user, :name, label: 'My label', required: true, id: 'name_label'
33
65
  assert_select 'label.string#name_label', /My label/
34
66
  assert_no_select 'label[label]'
35
67
  assert_no_select 'label[required]'
36
68
  end
37
69
 
38
- test 'builder should not modify the options hash' do
39
- options = { :label => 'My label', :id => 'name_label' }
70
+ test 'builder does not modify the options hash' do
71
+ options = { label: 'My label', id: 'name_label' }
40
72
  with_label_for @user, :name, options
41
73
  assert_select 'label.string#name_label', /My label/
42
- assert_equal({ :label => 'My label', :id => 'name_label' }, options)
74
+ assert_equal({ label: 'My label', id: 'name_label' }, options)
43
75
  end
44
76
 
45
- test 'builder should fallback to default label when string is given' do
77
+ test 'builder fallbacks to default label when string is given' do
46
78
  with_label_for @user, :name, 'Nome do usuário'
47
79
  assert_select 'label', 'Nome do usuário'
48
80
  assert_no_select 'label.string'
49
81
  end
50
82
 
51
- test 'builder should fallback to default label when block is given' do
83
+ test 'builder fallbacks to default label when block is given' do
52
84
  with_label_for @user, :name do
53
85
  'Nome do usuário'
54
86
  end
@@ -57,9 +89,48 @@ class LabelTest < ActionView::TestCase
57
89
  end
58
90
 
59
91
  test 'builder allows label order to be changed' do
60
- swap SimpleForm, :label_text => lambda { |l, r| "#{l}:" } do
92
+ swap SimpleForm, label_text: proc { |l, r| "#{l}:" } do
61
93
  with_label_for @user, :age
62
94
  assert_select 'label.integer[for=user_age]', "Age:"
63
95
  end
64
96
  end
97
+
98
+ test 'configuration allow set label text for wrappers' do
99
+ swap_wrapper :default, custom_wrapper_with_label_text do
100
+ with_concat_form_for(@user) do |f|
101
+ concat f.input :age
102
+ end
103
+ assert_select "label.integer[for=user_age]", "**Age**"
104
+ end
105
+ end
106
+
107
+ test 'configuration allow set rewrited label tag for wrappers' do
108
+ swap_wrapper :default, custom_wrapper_with_custom_label_component do
109
+ with_concat_form_for(@user) do |f|
110
+ concat f.input :age
111
+ end
112
+ assert_select "span.integer.user_age", /Age/
113
+ end
114
+ end
115
+
116
+ test 'builder allows custom formatting when label is explicitly specified' do
117
+ swap SimpleForm, label_text: ->(l, r, explicit_label) { explicit_label ? l : "#{l.titleize}:" } do
118
+ with_label_for @user, :time_zone, 'What is your home time zone?'
119
+ assert_select 'label[for=user_time_zone]', 'What is your home time zone?'
120
+ end
121
+ end
122
+
123
+ test 'builder allows custom formatting when label is generated' do
124
+ swap SimpleForm, label_text: ->(l, r, explicit_label) { explicit_label ? l : "#{l.titleize}:" } do
125
+ with_label_for @user, :time_zone
126
+ assert_select 'label[for=user_time_zone]', 'Time Zone:'
127
+ end
128
+ end
129
+
130
+ test 'builder allows label specific `label_text` option' do
131
+ with_label_for @user, :time_zone, label_text: ->(l, _, _) { "#{l.titleize}:" }
132
+
133
+ assert_no_select 'label[label_text]'
134
+ assert_select 'label[for=user_time_zone]', 'Time Zone:'
135
+ end
65
136
  end