simple_form 3.0.4 → 5.0.3

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