formtastic 2.1.0 → 4.0.0

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 (164) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/test.yml +61 -0
  4. data/.gitignore +4 -2
  5. data/CHANGELOG.md +52 -0
  6. data/Gemfile +1 -1
  7. data/Gemfile.lock +105 -0
  8. data/MIT-LICENSE +1 -1
  9. data/{README.textile → README.md} +204 -219
  10. data/RELEASE_PROCESS +3 -1
  11. data/Rakefile +27 -29
  12. data/app/assets/stylesheets/formtastic.css +3 -2
  13. data/bin/appraisal +8 -0
  14. data/formtastic.gemspec +11 -14
  15. data/gemfiles/rails_5.2/Gemfile +5 -0
  16. data/gemfiles/rails_6.0/Gemfile +5 -0
  17. data/gemfiles/rails_6.1/Gemfile +5 -0
  18. data/gemfiles/rails_edge/Gemfile +13 -0
  19. data/lib/formtastic/action_class_finder.rb +18 -0
  20. data/lib/formtastic/actions/button_action.rb +55 -60
  21. data/lib/formtastic/actions/input_action.rb +59 -57
  22. data/lib/formtastic/actions/link_action.rb +68 -67
  23. data/lib/formtastic/actions.rb +6 -3
  24. data/lib/formtastic/deprecation.rb +5 -0
  25. data/lib/formtastic/engine.rb +3 -1
  26. data/lib/formtastic/form_builder.rb +35 -16
  27. data/lib/formtastic/helpers/action_helper.rb +34 -28
  28. data/lib/formtastic/helpers/enum.rb +13 -0
  29. data/lib/formtastic/helpers/errors_helper.rb +2 -2
  30. data/lib/formtastic/helpers/fieldset_wrapper.rb +16 -12
  31. data/lib/formtastic/helpers/form_helper.rb +19 -16
  32. data/lib/formtastic/helpers/input_helper.rb +69 -97
  33. data/lib/formtastic/helpers/inputs_helper.rb +35 -25
  34. data/lib/formtastic/helpers/reflection.rb +4 -4
  35. data/lib/formtastic/helpers.rb +1 -2
  36. data/lib/formtastic/html_attributes.rb +12 -1
  37. data/lib/formtastic/i18n.rb +1 -1
  38. data/lib/formtastic/input_class_finder.rb +18 -0
  39. data/lib/formtastic/inputs/base/choices.rb +2 -2
  40. data/lib/formtastic/inputs/base/collections.rb +46 -14
  41. data/lib/formtastic/inputs/base/database.rb +7 -2
  42. data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
  43. data/lib/formtastic/inputs/base/errors.rb +7 -7
  44. data/lib/formtastic/inputs/base/hints.rb +2 -2
  45. data/lib/formtastic/inputs/base/html.rb +10 -9
  46. data/lib/formtastic/inputs/base/labelling.rb +5 -8
  47. data/lib/formtastic/inputs/base/naming.rb +4 -4
  48. data/lib/formtastic/inputs/base/numeric.rb +1 -1
  49. data/lib/formtastic/inputs/base/options.rb +3 -4
  50. data/lib/formtastic/inputs/base/stringish.rb +10 -2
  51. data/lib/formtastic/inputs/base/timeish.rb +34 -22
  52. data/lib/formtastic/inputs/base/validations.rb +41 -13
  53. data/lib/formtastic/inputs/base/wrapping.rb +29 -26
  54. data/lib/formtastic/inputs/base.rb +22 -15
  55. data/lib/formtastic/inputs/boolean_input.rb +26 -12
  56. data/lib/formtastic/inputs/check_boxes_input.rb +39 -31
  57. data/lib/formtastic/inputs/color_input.rb +41 -0
  58. data/lib/formtastic/inputs/country_input.rb +24 -5
  59. data/lib/formtastic/inputs/datalist_input.rb +41 -0
  60. data/lib/formtastic/inputs/date_picker_input.rb +93 -0
  61. data/lib/formtastic/inputs/{date_input.rb → date_select_input.rb} +1 -1
  62. data/lib/formtastic/inputs/datetime_picker_input.rb +103 -0
  63. data/lib/formtastic/inputs/{datetime_input.rb → datetime_select_input.rb} +1 -1
  64. data/lib/formtastic/inputs/file_input.rb +2 -2
  65. data/lib/formtastic/inputs/hidden_input.rb +2 -6
  66. data/lib/formtastic/inputs/radio_input.rb +28 -22
  67. data/lib/formtastic/inputs/select_input.rb +36 -39
  68. data/lib/formtastic/inputs/time_picker_input.rb +99 -0
  69. data/lib/formtastic/inputs/{time_input.rb → time_select_input.rb} +6 -2
  70. data/lib/formtastic/inputs/time_zone_input.rb +16 -6
  71. data/lib/formtastic/inputs.rb +32 -21
  72. data/lib/formtastic/localized_string.rb +1 -1
  73. data/lib/formtastic/localizer.rb +24 -24
  74. data/lib/formtastic/namespaced_class_finder.rb +99 -0
  75. data/lib/formtastic/version.rb +1 -1
  76. data/lib/formtastic.rb +20 -10
  77. data/lib/generators/formtastic/form/form_generator.rb +10 -4
  78. data/lib/generators/formtastic/input/input_generator.rb +46 -0
  79. data/lib/generators/formtastic/install/install_generator.rb +5 -19
  80. data/lib/generators/templates/_form.html.slim +2 -2
  81. data/lib/generators/templates/formtastic.rb +46 -25
  82. data/lib/generators/templates/input.rb +19 -0
  83. data/sample/basic_inputs.html +23 -3
  84. data/script/integration-template.rb +74 -0
  85. data/script/integration.sh +19 -0
  86. data/spec/action_class_finder_spec.rb +12 -0
  87. data/spec/actions/button_action_spec.rb +8 -8
  88. data/spec/actions/generic_action_spec.rb +92 -56
  89. data/spec/actions/input_action_spec.rb +7 -7
  90. data/spec/actions/link_action_spec.rb +10 -10
  91. data/spec/builder/custom_builder_spec.rb +36 -20
  92. data/spec/builder/error_proc_spec.rb +4 -4
  93. data/spec/builder/semantic_fields_for_spec.rb +28 -29
  94. data/spec/fast_spec_helper.rb +12 -0
  95. data/spec/generators/formtastic/form/form_generator_spec.rb +45 -32
  96. data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
  97. data/spec/generators/formtastic/install/install_generator_spec.rb +9 -9
  98. data/spec/helpers/action_helper_spec.rb +75 -103
  99. data/spec/helpers/actions_helper_spec.rb +17 -17
  100. data/spec/helpers/form_helper_spec.rb +84 -33
  101. data/spec/helpers/input_helper_spec.rb +333 -285
  102. data/spec/helpers/inputs_helper_spec.rb +167 -121
  103. data/spec/helpers/reflection_helper_spec.rb +3 -3
  104. data/spec/helpers/semantic_errors_helper_spec.rb +23 -23
  105. data/spec/i18n_spec.rb +26 -26
  106. data/spec/input_class_finder_spec.rb +10 -0
  107. data/spec/inputs/base/collections_spec.rb +76 -0
  108. data/spec/inputs/base/validations_spec.rb +480 -0
  109. data/spec/inputs/boolean_input_spec.rb +100 -65
  110. data/spec/inputs/check_boxes_input_spec.rb +200 -101
  111. data/spec/inputs/color_input_spec.rb +85 -0
  112. data/spec/inputs/country_input_spec.rb +20 -20
  113. data/spec/inputs/custom_input_spec.rb +3 -4
  114. data/spec/inputs/datalist_input_spec.rb +61 -0
  115. data/spec/inputs/date_picker_input_spec.rb +449 -0
  116. data/spec/inputs/date_select_input_spec.rb +249 -0
  117. data/spec/inputs/datetime_picker_input_spec.rb +490 -0
  118. data/spec/inputs/datetime_select_input_spec.rb +209 -0
  119. data/spec/inputs/email_input_spec.rb +5 -5
  120. data/spec/inputs/file_input_spec.rb +6 -6
  121. data/spec/inputs/hidden_input_spec.rb +22 -35
  122. data/spec/inputs/include_blank_spec.rb +11 -11
  123. data/spec/inputs/label_spec.rb +62 -25
  124. data/spec/inputs/number_input_spec.rb +112 -112
  125. data/spec/inputs/password_input_spec.rb +5 -5
  126. data/spec/inputs/phone_input_spec.rb +5 -5
  127. data/spec/inputs/placeholder_spec.rb +6 -6
  128. data/spec/inputs/radio_input_spec.rb +99 -55
  129. data/spec/inputs/range_input_spec.rb +66 -66
  130. data/spec/inputs/readonly_spec.rb +50 -0
  131. data/spec/inputs/search_input_spec.rb +5 -5
  132. data/spec/inputs/select_input_spec.rb +170 -170
  133. data/spec/inputs/string_input_spec.rb +68 -16
  134. data/spec/inputs/text_input_spec.rb +16 -16
  135. data/spec/inputs/time_picker_input_spec.rb +455 -0
  136. data/spec/inputs/time_select_input_spec.rb +261 -0
  137. data/spec/inputs/time_zone_input_spec.rb +54 -28
  138. data/spec/inputs/url_input_spec.rb +5 -5
  139. data/spec/inputs/with_options_spec.rb +7 -7
  140. data/spec/localizer_spec.rb +39 -17
  141. data/spec/namespaced_class_finder_spec.rb +79 -0
  142. data/spec/schema.rb +21 -0
  143. data/spec/spec_helper.rb +254 -221
  144. data/spec/support/custom_macros.rb +128 -95
  145. data/spec/support/shared_examples.rb +12 -0
  146. data/spec/support/specialized_class_finder_shared_example.rb +27 -0
  147. data/spec/support/test_environment.rb +26 -10
  148. metadata +177 -238
  149. data/.travis.yml +0 -8
  150. data/Appraisals +0 -11
  151. data/CHANGELOG +0 -371
  152. data/gemfiles/rails-3.0.gemfile +0 -7
  153. data/gemfiles/rails-3.1.gemfile +0 -7
  154. data/gemfiles/rails-3.2.gemfile +0 -7
  155. data/lib/formtastic/helpers/buttons_helper.rb +0 -310
  156. data/lib/formtastic/inputs/base/grouped_collections.rb +0 -77
  157. data/lib/formtastic/util.rb +0 -25
  158. data/lib/tasks/verify_rcov.rb +0 -44
  159. data/spec/helpers/buttons_helper_spec.rb +0 -166
  160. data/spec/helpers/commit_button_helper_spec.rb +0 -530
  161. data/spec/inputs/date_input_spec.rb +0 -227
  162. data/spec/inputs/datetime_input_spec.rb +0 -185
  163. data/spec/inputs/time_input_spec.rb +0 -267
  164. data/spec/support/deferred_garbage_collection.rb +0 -21
@@ -0,0 +1,249 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ RSpec.describe 'date select input' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ end
12
+
13
+ describe "general" do
14
+
15
+ before do
16
+ output_buffer.replace ''
17
+ concat(semantic_form_for(@new_post) do |builder|
18
+ concat(builder.input(:publish_at, :as => :date_select, :order => [:year, :month, :day]))
19
+ end)
20
+ end
21
+
22
+ it_should_have_input_wrapper_with_class("date_select")
23
+ it_should_have_input_wrapper_with_class(:input)
24
+ it_should_have_input_wrapper_with_id("post_publish_at_input")
25
+ it_should_have_a_nested_fieldset
26
+ it_should_have_a_nested_fieldset_with_class('fragments')
27
+ it_should_have_a_nested_ordered_list_with_class('fragments-group')
28
+ it_should_apply_error_logic_for_input_type(:date_select)
29
+
30
+ it 'should have a legend and label with the label text inside the fieldset' do
31
+ expect(output_buffer).to have_tag('form li.date_select fieldset legend.label label', :text => /Publish at/)
32
+ end
33
+
34
+ it 'should associate the legend label with the first select' do
35
+ expect(output_buffer).to have_tag('form li.date_select fieldset legend.label')
36
+ expect(output_buffer).to have_tag('form li.date_select fieldset legend.label label')
37
+ expect(output_buffer).to have_tag('form li.date_select fieldset legend.label label[@for]')
38
+ expect(output_buffer).to have_tag('form li.date_select fieldset legend.label label[@for="post_publish_at_1i"]')
39
+ end
40
+
41
+ it 'should have an ordered list of three items inside the fieldset' do
42
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol.fragments-group')
43
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li.fragment', :count => 3)
44
+ end
45
+
46
+ it 'should have three labels for year, month and day' do
47
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li label', :count => 3)
48
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li label', :text => /year/i)
49
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li label', :text => /month/i)
50
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li label', :text => /day/i)
51
+ end
52
+
53
+ it 'should have three selects for year, month and day' do
54
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li select', :count => 3)
55
+ end
56
+ end
57
+
58
+ describe "when namespace is provided" do
59
+
60
+ before do
61
+ output_buffer.replace ''
62
+ concat(semantic_form_for(@new_post, :namespace => "context2") do |builder|
63
+ concat(builder.input(:publish_at, :as => :date_select, :order => [:year, :month, :day]))
64
+ end)
65
+ end
66
+
67
+ it_should_have_input_wrapper_with_id("context2_post_publish_at_input")
68
+ it_should_have_select_with_id("context2_post_publish_at_1i")
69
+ it_should_have_select_with_id("context2_post_publish_at_2i")
70
+ it_should_have_select_with_id("context2_post_publish_at_3i")
71
+
72
+ end
73
+
74
+ describe "when index is provided" do
75
+
76
+ before do
77
+ @output_buffer = ''
78
+ mock_everything
79
+
80
+ concat(semantic_form_for(@new_post) do |builder|
81
+ concat(builder.fields_for(:author, :index => 3) do |author|
82
+ concat(author.input(:created_at, :as => :date_select))
83
+ end)
84
+ end)
85
+ end
86
+
87
+ it 'should index the id of the wrapper' do
88
+ expect(output_buffer).to have_tag("li#post_author_attributes_3_created_at_input")
89
+ end
90
+
91
+ it 'should index the id of the select tag' do
92
+ expect(output_buffer).to have_tag("select#post_author_attributes_3_created_at_1i")
93
+ expect(output_buffer).to have_tag("select#post_author_attributes_3_created_at_2i")
94
+ expect(output_buffer).to have_tag("select#post_author_attributes_3_created_at_3i")
95
+ end
96
+
97
+ it 'should index the name of the select tag' do
98
+ expect(output_buffer).to have_tag("select[@name='post[author_attributes][3][created_at(1i)]']")
99
+ expect(output_buffer).to have_tag("select[@name='post[author_attributes][3][created_at(2i)]']")
100
+ expect(output_buffer).to have_tag("select[@name='post[author_attributes][3][created_at(3i)]']")
101
+ end
102
+
103
+ end
104
+
105
+ describe ':labels option' do
106
+ fields = [:year, :month, :day]
107
+ fields.each do |field|
108
+ it "should replace the #{field} label with the specified text if :labels[:#{field}] is set" do
109
+ output_buffer.replace ''
110
+ concat(semantic_form_for(@new_post) do |builder|
111
+ concat(builder.input(:created_at, :as => :date_select, :labels => { field => "another #{field} label" }))
112
+ end)
113
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li label', :count => fields.length)
114
+ fields.each do |f|
115
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li label', :text => f == field ? /another #{f} label/i : /#{f}/i)
116
+ end
117
+ end
118
+
119
+ it "should not display the label for the #{field} field when :labels[:#{field}] is blank" do
120
+ output_buffer.replace ''
121
+ concat(semantic_form_for(@new_post) do |builder|
122
+ concat(builder.input(:created_at, :as => :date_select, :labels => { field => "" }))
123
+ end)
124
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li label', :count => fields.length-1)
125
+ fields.each do |f|
126
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li label', :text => /#{f}/i) unless field == f
127
+ end
128
+ end
129
+
130
+ it "should not display the label for the #{field} field when :labels[:#{field}] is false" do
131
+ output_buffer.replace ''
132
+ concat(semantic_form_for(@new_post) do |builder|
133
+ concat(builder.input(:created_at, :as => :date_select, :labels => { field => false }))
134
+ end)
135
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li label', :count => fields.length-1)
136
+ fields.each do |f|
137
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li label', /#{f}/i) unless field == f
138
+ end
139
+ end
140
+
141
+ it "should not render unsafe HTML when :labels[:#{field}] is false" do
142
+ output_buffer.replace ''
143
+ concat(semantic_form_for(@new_post) do |builder|
144
+ concat(builder.input(:created_at, :as => :date_select, :include_seconds => true, :labels => { field => false }))
145
+ end)
146
+ expect(output_buffer).not_to include(">")
147
+ end
148
+
149
+ end
150
+
151
+ it "should not display labels for any fields when :labels is falsy" do
152
+ output_buffer.replace ''
153
+ concat(semantic_form_for(@new_post) do |builder|
154
+ concat(builder.input(:created_at, :as => :date_select, :labels => false))
155
+ end)
156
+ expect(output_buffer).to have_tag('form li.date_select fieldset ol li label', :count => 0)
157
+ end
158
+ end
159
+
160
+ describe ":selected option for setting a value" do
161
+ it "should set the selected value for the form" do
162
+ concat(
163
+ semantic_form_for(@new_post) do |f|
164
+ concat(f.input(:created_at, :as => :datetime_select, :selected => Date.new(2018, 10, 4)))
165
+ end
166
+ )
167
+
168
+ expect(output_buffer).to have_tag "option[value='2018'][selected='selected']"
169
+ expect(output_buffer).to have_tag "option[value='10'][selected='selected']"
170
+ expect(output_buffer).to have_tag "option[value='4'][selected='selected']"
171
+ end
172
+ end
173
+
174
+ describe "when required" do
175
+ it "should add the required attribute to the input's html options" do
176
+ with_config :use_required_attribute, true do
177
+ concat(semantic_form_for(@new_post) do |builder|
178
+ concat(builder.input(:title, :as => :date_select, :required => true))
179
+ end)
180
+ expect(output_buffer).to have_tag("select[@required]", :count => 3)
181
+ end
182
+ end
183
+ end
184
+
185
+ describe "when order does not include day" do
186
+ before do
187
+ output_buffer.replace ''
188
+ concat(semantic_form_for(@new_post) do |builder|
189
+ concat(builder.input(:publish_at, :as => :date_select, :order => [:year, :month]))
190
+ end)
191
+ end
192
+
193
+ it "should include a hidden input for day" do
194
+ expect(output_buffer).to have_tag('input[@type="hidden"][@name="post[publish_at(3i)]"][@value="1"]')
195
+ end
196
+
197
+ it "should not include a select for day" do
198
+ expect(output_buffer).not_to have_tag('select[@name="post[publish_at(3i)]"]')
199
+ end
200
+ end
201
+
202
+ describe "when order does not include month" do
203
+ before do
204
+ output_buffer.replace ''
205
+ concat(semantic_form_for(@new_post) do |builder|
206
+ concat(builder.input(:publish_at, :as => :date_select, :order => [:year, :day]))
207
+ end)
208
+ end
209
+
210
+ it "should include a hidden input for month" do
211
+ expect(output_buffer).to have_tag('input[@type="hidden"][@name="post[publish_at(2i)]"][@value="1"]')
212
+ end
213
+
214
+ it "should not include a select for month" do
215
+ expect(output_buffer).not_to have_tag('select[@name="post[publish_at(2i)]"]')
216
+ end
217
+ end
218
+
219
+ describe "when order does not include year" do
220
+ before do
221
+ output_buffer.replace ''
222
+ concat(semantic_form_for(@new_post) do |builder|
223
+ concat(builder.input(:publish_at, :as => :date_select, :order => [:month, :day]))
224
+ end)
225
+ end
226
+
227
+ it "should include a hidden input for month" do
228
+ expect(output_buffer).to have_tag("input[@type=\"hidden\"][@name=\"post[publish_at(1i)]\"][@value=\"#{Time.now.year}\"]")
229
+ end
230
+
231
+ it "should not include a select for month" do
232
+ expect(output_buffer).not_to have_tag('select[@name="post[publish_at(1i)]"]')
233
+ end
234
+ end
235
+
236
+ describe "when order does not have year first" do
237
+ before do
238
+ output_buffer.replace ''
239
+ concat(semantic_form_for(@new_post) do |builder|
240
+ concat(builder.input(:publish_at, :as => :date_select, :order => [:day, :month, :year]))
241
+ end)
242
+ end
243
+
244
+ it 'should associate the legend label with the new first select' do
245
+ expect(output_buffer).to have_tag('form li.date_select fieldset legend.label label[@for="post_publish_at_3i"]')
246
+ end
247
+ end
248
+
249
+ end