formtastic 3.0.0 → 5.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 (175) hide show
  1. checksums.yaml +5 -13
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/test.yml +61 -0
  4. data/.gitignore +3 -2
  5. data/CHANGELOG.md +61 -0
  6. data/Gemfile.lock +140 -0
  7. data/MIT-LICENSE +1 -1
  8. data/{README.textile → README.md} +191 -168
  9. data/RELEASE_PROCESS +3 -1
  10. data/Rakefile +24 -8
  11. data/app/assets/stylesheets/formtastic.css +1 -1
  12. data/bin/appraisal +8 -0
  13. data/formtastic.gemspec +13 -17
  14. data/gemfiles/rails_6.0/Gemfile +5 -0
  15. data/gemfiles/rails_6.1/Gemfile +5 -0
  16. data/gemfiles/rails_7.0/Gemfile +5 -0
  17. data/gemfiles/rails_7.1/Gemfile +5 -0
  18. data/gemfiles/rails_edge/Gemfile +13 -0
  19. data/lib/formtastic/action_class_finder.rb +19 -0
  20. data/lib/formtastic/actions/base.rb +1 -0
  21. data/lib/formtastic/actions/button_action.rb +56 -53
  22. data/lib/formtastic/actions/buttonish.rb +1 -0
  23. data/lib/formtastic/actions/input_action.rb +60 -57
  24. data/lib/formtastic/actions/link_action.rb +69 -67
  25. data/lib/formtastic/actions.rb +7 -3
  26. data/lib/formtastic/deprecation.rb +6 -0
  27. data/lib/formtastic/engine.rb +4 -1
  28. data/lib/formtastic/form_builder.rb +32 -25
  29. data/lib/formtastic/helpers/action_helper.rb +22 -31
  30. data/lib/formtastic/helpers/actions_helper.rb +1 -0
  31. data/lib/formtastic/helpers/enum.rb +14 -0
  32. data/lib/formtastic/helpers/errors_helper.rb +3 -2
  33. data/lib/formtastic/helpers/fieldset_wrapper.rb +16 -11
  34. data/lib/formtastic/helpers/file_column_detection.rb +1 -0
  35. data/lib/formtastic/helpers/form_helper.rb +4 -3
  36. data/lib/formtastic/helpers/input_helper.rb +59 -80
  37. data/lib/formtastic/helpers/inputs_helper.rb +33 -27
  38. data/lib/formtastic/helpers/reflection.rb +5 -4
  39. data/lib/formtastic/helpers.rb +2 -2
  40. data/lib/formtastic/html_attributes.rb +13 -1
  41. data/lib/formtastic/i18n.rb +2 -1
  42. data/lib/formtastic/input_class_finder.rb +19 -0
  43. data/lib/formtastic/inputs/base/associations.rb +1 -0
  44. data/lib/formtastic/inputs/base/choices.rb +4 -3
  45. data/lib/formtastic/inputs/base/collections.rb +47 -11
  46. data/lib/formtastic/inputs/base/database.rb +8 -5
  47. data/lib/formtastic/inputs/base/datetime_pickerish.rb +1 -0
  48. data/lib/formtastic/inputs/base/errors.rb +7 -6
  49. data/lib/formtastic/inputs/base/fileish.rb +1 -0
  50. data/lib/formtastic/inputs/base/hints.rb +2 -1
  51. data/lib/formtastic/inputs/base/html.rb +12 -10
  52. data/lib/formtastic/inputs/base/labelling.rb +3 -2
  53. data/lib/formtastic/inputs/base/naming.rb +5 -4
  54. data/lib/formtastic/inputs/base/numeric.rb +1 -0
  55. data/lib/formtastic/inputs/base/options.rb +3 -3
  56. data/lib/formtastic/inputs/base/placeholder.rb +1 -0
  57. data/lib/formtastic/inputs/base/stringish.rb +1 -0
  58. data/lib/formtastic/inputs/base/timeish.rb +9 -4
  59. data/lib/formtastic/inputs/base/validations.rb +39 -12
  60. data/lib/formtastic/inputs/base/wrapping.rb +2 -3
  61. data/lib/formtastic/inputs/base.rb +17 -12
  62. data/lib/formtastic/inputs/boolean_input.rb +2 -1
  63. data/lib/formtastic/inputs/check_boxes_input.rb +16 -24
  64. data/lib/formtastic/inputs/color_input.rb +1 -1
  65. data/lib/formtastic/inputs/country_input.rb +4 -1
  66. data/lib/formtastic/inputs/datalist_input.rb +42 -0
  67. data/lib/formtastic/inputs/date_picker_input.rb +1 -0
  68. data/lib/formtastic/inputs/date_select_input.rb +1 -0
  69. data/lib/formtastic/inputs/datetime_picker_input.rb +1 -0
  70. data/lib/formtastic/inputs/datetime_select_input.rb +1 -0
  71. data/lib/formtastic/inputs/email_input.rb +1 -0
  72. data/lib/formtastic/inputs/file_input.rb +3 -2
  73. data/lib/formtastic/inputs/hidden_input.rb +3 -2
  74. data/lib/formtastic/inputs/number_input.rb +1 -0
  75. data/lib/formtastic/inputs/password_input.rb +1 -0
  76. data/lib/formtastic/inputs/phone_input.rb +1 -0
  77. data/lib/formtastic/inputs/radio_input.rb +26 -21
  78. data/lib/formtastic/inputs/range_input.rb +1 -0
  79. data/lib/formtastic/inputs/search_input.rb +1 -0
  80. data/lib/formtastic/inputs/select_input.rb +32 -10
  81. data/lib/formtastic/inputs/string_input.rb +1 -0
  82. data/lib/formtastic/inputs/text_input.rb +1 -0
  83. data/lib/formtastic/inputs/time_picker_input.rb +1 -0
  84. data/lib/formtastic/inputs/time_select_input.rb +1 -0
  85. data/lib/formtastic/inputs/time_zone_input.rb +17 -6
  86. data/lib/formtastic/inputs/url_input.rb +1 -0
  87. data/lib/formtastic/inputs.rb +33 -28
  88. data/lib/formtastic/localized_string.rb +2 -1
  89. data/lib/formtastic/localizer.rb +23 -24
  90. data/lib/formtastic/namespaced_class_finder.rb +98 -0
  91. data/lib/formtastic/version.rb +2 -1
  92. data/lib/formtastic.rb +19 -14
  93. data/lib/generators/formtastic/form/form_generator.rb +8 -2
  94. data/lib/generators/formtastic/input/input_generator.rb +47 -0
  95. data/lib/generators/formtastic/install/install_generator.rb +2 -0
  96. data/lib/generators/templates/formtastic.rb +29 -7
  97. data/lib/generators/templates/input.rb +19 -0
  98. data/sample/basic_inputs.html +1 -1
  99. data/script/integration-template.rb +73 -0
  100. data/script/integration.sh +19 -0
  101. data/spec/action_class_finder_spec.rb +13 -0
  102. data/spec/actions/button_action_spec.rb +21 -20
  103. data/spec/actions/generic_action_spec.rb +134 -133
  104. data/spec/actions/input_action_spec.rb +20 -19
  105. data/spec/actions/link_action_spec.rb +30 -29
  106. data/spec/builder/custom_builder_spec.rb +39 -22
  107. data/spec/builder/error_proc_spec.rb +6 -5
  108. data/spec/builder/semantic_fields_for_spec.rb +46 -45
  109. data/spec/fast_spec_helper.rb +13 -0
  110. data/spec/generators/formtastic/form/form_generator_spec.rb +33 -32
  111. data/spec/generators/formtastic/input/input_generator_spec.rb +125 -0
  112. data/spec/generators/formtastic/install/install_generator_spec.rb +10 -9
  113. data/spec/helpers/action_helper_spec.rb +70 -97
  114. data/spec/helpers/actions_helper_spec.rb +43 -42
  115. data/spec/helpers/form_helper_spec.rb +56 -39
  116. data/spec/helpers/input_helper_spec.rb +314 -255
  117. data/spec/helpers/inputs_helper_spec.rb +217 -202
  118. data/spec/helpers/reflection_helper_spec.rb +7 -6
  119. data/spec/helpers/semantic_errors_helper_spec.rb +26 -25
  120. data/spec/i18n_spec.rb +30 -29
  121. data/spec/input_class_finder_spec.rb +11 -0
  122. data/spec/inputs/base/collections_spec.rb +78 -0
  123. data/spec/inputs/base/validations_spec.rb +481 -0
  124. data/spec/inputs/boolean_input_spec.rb +73 -72
  125. data/spec/inputs/check_boxes_input_spec.rb +174 -123
  126. data/spec/inputs/color_input_spec.rb +53 -64
  127. data/spec/inputs/country_input_spec.rb +23 -22
  128. data/spec/inputs/custom_input_spec.rb +3 -6
  129. data/spec/inputs/datalist_input_spec.rb +62 -0
  130. data/spec/inputs/date_picker_input_spec.rb +114 -113
  131. data/spec/inputs/date_select_input_spec.rb +76 -61
  132. data/spec/inputs/datetime_picker_input_spec.rb +123 -122
  133. data/spec/inputs/datetime_select_input_spec.rb +85 -68
  134. data/spec/inputs/email_input_spec.rb +17 -16
  135. data/spec/inputs/file_input_spec.rb +18 -17
  136. data/spec/inputs/hidden_input_spec.rb +32 -31
  137. data/spec/inputs/include_blank_spec.rb +10 -9
  138. data/spec/inputs/label_spec.rb +36 -31
  139. data/spec/inputs/number_input_spec.rb +212 -211
  140. data/spec/inputs/password_input_spec.rb +17 -16
  141. data/spec/inputs/phone_input_spec.rb +17 -16
  142. data/spec/inputs/placeholder_spec.rb +18 -17
  143. data/spec/inputs/radio_input_spec.rb +92 -65
  144. data/spec/inputs/range_input_spec.rb +136 -135
  145. data/spec/inputs/readonly_spec.rb +51 -0
  146. data/spec/inputs/search_input_spec.rb +16 -15
  147. data/spec/inputs/select_input_spec.rb +209 -102
  148. data/spec/inputs/string_input_spec.rb +51 -50
  149. data/spec/inputs/text_input_spec.rb +34 -33
  150. data/spec/inputs/time_picker_input_spec.rb +115 -114
  151. data/spec/inputs/time_select_input_spec.rb +84 -70
  152. data/spec/inputs/time_zone_input_spec.rb +58 -31
  153. data/spec/inputs/url_input_spec.rb +17 -16
  154. data/spec/inputs/with_options_spec.rb +9 -8
  155. data/spec/localizer_spec.rb +18 -17
  156. data/spec/namespaced_class_finder_spec.rb +91 -0
  157. data/spec/schema.rb +22 -0
  158. data/spec/spec_helper.rb +180 -249
  159. data/spec/support/custom_macros.rb +128 -98
  160. data/spec/support/deprecation.rb +2 -1
  161. data/spec/support/shared_examples.rb +13 -0
  162. data/spec/support/specialized_class_finder_shared_example.rb +28 -0
  163. data/spec/support/test_environment.rb +25 -10
  164. metadata +95 -136
  165. data/.travis.yml +0 -28
  166. data/Appraisals +0 -25
  167. data/CHANGELOG +0 -27
  168. data/gemfiles/rails_3.2.gemfile +0 -7
  169. data/gemfiles/rails_4.0.4.gemfile +0 -7
  170. data/gemfiles/rails_4.1.gemfile +0 -7
  171. data/gemfiles/rails_4.gemfile +0 -7
  172. data/gemfiles/rails_edge.gemfile +0 -10
  173. data/lib/formtastic/util.rb +0 -53
  174. data/spec/support/deferred_garbage_collection.rb +0 -21
  175. data/spec/util_spec.rb +0 -52
@@ -1,12 +1,13 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  require 'spec_helper'
3
4
 
4
- describe 'select input' do
5
+ RSpec.describe 'select input' do
5
6
 
6
7
  include FormtasticSpecHelper
7
8
 
8
9
  before do
9
- @output_buffer = ''
10
+ @output_buffer = ActionView::OutputBuffer.new ''
10
11
  mock_everything
11
12
  end
12
13
 
@@ -23,14 +24,14 @@ describe 'select input' do
23
24
 
24
25
  it 'should have a option for each key and/or value' do
25
26
  @array_with_values.each do |v|
26
- output_buffer.should have_tag("form li select option[@value='#{v}']", /^#{v}$/)
27
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='#{v}']", :text => /^#{v}$/)
27
28
  end
28
29
  @array_with_keys_and_values.each do |v|
29
- output_buffer.should have_tag("form li select option[@value='#{v.second}']", /^#{v.first}$/)
30
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='#{v.second}']", :text => /^#{v.first}$/)
30
31
  end
31
32
  end
32
33
  end
33
-
34
+
34
35
  describe 'using a set of values' do
35
36
  before do
36
37
  @set_with_values = Set.new(["Title A", "Title B", "Title C"])
@@ -43,26 +44,26 @@ describe 'select input' do
43
44
 
44
45
  it 'should have a option for each key and/or value' do
45
46
  @set_with_values.each do |v|
46
- output_buffer.should have_tag("form li select option[@value='#{v}']", /^#{v}$/)
47
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='#{v}']", :text => /^#{v}$/)
47
48
  end
48
49
  @set_with_keys_and_values.each do |v|
49
- output_buffer.should have_tag("form li select option[@value='#{v.second}']", /^#{v.first}$/)
50
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='#{v.second}']", :text => /^#{v.first}$/)
50
51
  end
51
52
  end
52
53
  end
53
54
 
54
55
  describe "using a related model without reflection's options (Mongoid Document)" do
55
56
  before do
56
- @new_post.stub(:mongoid_reviewer)
57
+ allow(@new_post).to receive(:mongoid_reviewer)
57
58
  concat(semantic_form_for(@new_post) do |builder|
58
59
  concat(builder.input(:mongoid_reviewer, :as => :select))
59
60
  end)
60
61
  end
61
62
 
62
63
  it 'should draw select options' do
63
- output_buffer.should have_tag('form li select')
64
- output_buffer.should have_tag('form li select#post_reviewer_id')
65
- output_buffer.should_not have_tag('form li select#post_mongoid_reviewer_id')
64
+ expect(output_buffer.to_str).to have_tag('form li select')
65
+ expect(output_buffer.to_str).to have_tag('form li select#post_reviewer_id')
66
+ expect(output_buffer.to_str).not_to have_tag('form li select#post_mongoid_reviewer_id')
66
67
  end
67
68
  end
68
69
 
@@ -76,7 +77,7 @@ describe 'select input' do
76
77
 
77
78
  it 'should have an option for each value' do
78
79
  @range_with_values.each do |v|
79
- output_buffer.should have_tag("form li select option[@value='#{v}']", /^#{v}$/)
80
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='#{v}']", :text => /^#{v}$/)
80
81
  end
81
82
  end
82
83
  end
@@ -91,7 +92,7 @@ describe 'select input' do
91
92
 
92
93
  it 'should render select options using provided HTML string' do
93
94
  2.times do |v|
94
- output_buffer.should have_tag("form li select option[@value='#{v}']", /^#{v}$/)
95
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='#{v}']", :text => /^#{v}$/)
95
96
  end
96
97
  end
97
98
  end
@@ -125,8 +126,8 @@ describe 'select input' do
125
126
  end
126
127
 
127
128
  it 'should render a select with at least options: true/false' do
128
- output_buffer.should have_tag("form li select option[@value='true']", /^Yes$/)
129
- output_buffer.should have_tag("form li select option[@value='false']", /^No$/)
129
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='true']", :text => /^Yes$/)
130
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='false']", :text => /^No$/)
130
131
  end
131
132
  end
132
133
 
@@ -145,8 +146,110 @@ describe 'select input' do
145
146
  end
146
147
 
147
148
  it 'should render a select with at least options: true/false' do
148
- output_buffer.should have_tag("form li select option[@value='true']", /#{@boolean_select_labels[:yes]}/)
149
- output_buffer.should have_tag("form li select option[@value='false']", /#{@boolean_select_labels[:no]}/)
149
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='true']", :text => /#{@boolean_select_labels[:yes]}/)
150
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='false']", :text => /#{@boolean_select_labels[:no]}/)
151
+ end
152
+ end
153
+ end
154
+
155
+ describe 'for a enum column' do
156
+ before do
157
+ allow(@new_post).to receive(:status) { 'inactive' }
158
+ statuses = ActiveSupport::HashWithIndifferentAccess.new("active"=>0, "inactive"=>1)
159
+ allow(@new_post.class).to receive(:statuses) { statuses }
160
+ allow(@new_post).to receive(:defined_enums) { { "status" => statuses } }
161
+ end
162
+
163
+ context 'with translations in a nested association input' do
164
+ before do
165
+ ::I18n.backend.store_translations :en, activerecord: {
166
+ attributes: {
167
+ post: {
168
+ statuses: {
169
+ active: 'I am active',
170
+ inactive: 'I am inactive'
171
+ }
172
+ }
173
+ }
174
+ }
175
+
176
+ allow(@fred).to receive(:posts).and_return([@new_post])
177
+ concat(semantic_form_for(@fred) do |builder|
178
+ concat(builder.inputs(for: @fred.posts.first) do |nested_builder|
179
+ nested_builder.input(:status, as: :select)
180
+ end)
181
+ end)
182
+ end
183
+
184
+ after do
185
+ ::I18n.backend.reload!
186
+ end
187
+
188
+ it 'should use localized enum values' do
189
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='active']", text: 'I am active')
190
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='inactive']", text: 'I am inactive')
191
+ end
192
+ end
193
+
194
+ context 'single choice' do
195
+ before do
196
+ concat(semantic_form_for(@new_post) do |builder|
197
+ concat(builder.input(:status, :as => :select))
198
+ end)
199
+ end
200
+
201
+ it_should_have_input_wrapper_with_class("select")
202
+ it_should_have_input_wrapper_with_class(:input)
203
+ it_should_have_input_wrapper_with_id("post_status_input")
204
+ it_should_have_label_with_text(/Status/)
205
+ it_should_have_label_for('post_status')
206
+ it_should_apply_error_logic_for_input_type(:select)
207
+
208
+ it 'should have a select inside the wrapper' do
209
+ expect(output_buffer.to_str).to have_tag('form li select')
210
+ expect(output_buffer.to_str).to have_tag('form li select#post_status')
211
+ end
212
+
213
+ it 'should have a valid name' do
214
+ expect(output_buffer.to_str).to have_tag("form li select[@name='post[status]']")
215
+ expect(output_buffer.to_str).not_to have_tag("form li select[@name='post[status][]']")
216
+ end
217
+
218
+ it 'should not create a multi-select' do
219
+ expect(output_buffer.to_str).not_to have_tag('form li select[@multiple]')
220
+ end
221
+
222
+ it 'should not add a hidden input' do
223
+ expect(output_buffer.to_str).not_to have_tag('form li input[@type="hidden"]')
224
+ end
225
+
226
+ it 'should create a select without size' do
227
+ expect(output_buffer.to_str).not_to have_tag('form li select[@size]')
228
+ end
229
+
230
+ it 'should have a blank option' do
231
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='']")
232
+ end
233
+
234
+ it 'should have a select option for each defined enum status' do
235
+ expect(output_buffer.to_str).to have_tag("form li select[@name='post[status]'] option", :count => @new_post.class.statuses.count + 1)
236
+ @new_post.class.statuses.each do |label, value|
237
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='#{label}']", :text => /#{label.humanize}/)
238
+ end
239
+ end
240
+
241
+ it 'should have one option with a "selected" attribute (TODO)' do
242
+ expect(output_buffer.to_str).to have_tag("form li select[@name='post[status]'] option[@selected]", :count => 1)
243
+ end
244
+ end
245
+
246
+ context 'multiple choice' do
247
+ it 'raises an error' do
248
+ expect {
249
+ concat(semantic_form_for(@new_post) do |builder|
250
+ concat(builder.input(:status, :as => :select, :multiple => true))
251
+ end)
252
+ }.to raise_error Formtastic::UnsupportedEnumCollection
150
253
  end
151
254
  end
152
255
  end
@@ -169,84 +272,88 @@ describe 'select input' do
169
272
  it_should_use_the_collection_when_provided(:select, 'option')
170
273
 
171
274
  it 'should have a select inside the wrapper' do
172
- output_buffer.should have_tag('form li select')
173
- output_buffer.should have_tag('form li select#post_author_id')
174
- output_buffer.should have_tag('form li select#post_reviewer_id')
275
+ expect(output_buffer.to_str).to have_tag('form li select')
276
+ expect(output_buffer.to_str).to have_tag('form li select#post_author_id')
277
+ expect(output_buffer.to_str).to have_tag('form li select#post_reviewer_id')
175
278
  end
176
279
 
177
280
  it 'should have a valid name' do
178
- output_buffer.should have_tag("form li select[@name='post[author_id]']")
179
- output_buffer.should_not have_tag("form li select[@name='post[author_id][]']")
180
- output_buffer.should_not have_tag("form li select[@name='post[reviewer_id][]']")
281
+ expect(output_buffer.to_str).to have_tag("form li select[@name='post[author_id]']")
282
+ expect(output_buffer.to_str).not_to have_tag("form li select[@name='post[author_id][]']")
283
+ expect(output_buffer.to_str).not_to have_tag("form li select[@name='post[reviewer_id][]']")
181
284
  end
182
285
 
183
286
  it 'should not create a multi-select' do
184
- output_buffer.should_not have_tag('form li select[@multiple]')
287
+ expect(output_buffer.to_str).not_to have_tag('form li select[@multiple]')
185
288
  end
186
-
289
+
187
290
  it 'should not add a hidden input' do
188
- output_buffer.should_not have_tag('form li input[@type="hidden"]')
291
+ expect(output_buffer.to_str).not_to have_tag('form li input[@type="hidden"]')
189
292
  end
190
293
 
191
294
  it 'should create a select without size' do
192
- output_buffer.should_not have_tag('form li select[@size]')
295
+ expect(output_buffer.to_str).not_to have_tag('form li select[@size]')
193
296
  end
194
297
 
195
298
  it 'should have a blank option' do
196
- output_buffer.should have_tag("form li select option[@value='']")
299
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='']")
197
300
  end
198
301
 
199
302
  it 'should have a select option for each Author' do
200
- output_buffer.should have_tag("form li select[@name='post[author_id]'] option", :count => ::Author.all.size + 1)
303
+ expect(output_buffer.to_str).to have_tag("form li select[@name='post[author_id]'] option", :count => ::Author.all.size + 1)
201
304
  ::Author.all.each do |author|
202
- output_buffer.should have_tag("form li select option[@value='#{author.id}']", /#{author.to_label}/)
305
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='#{author.id}']", :text => /#{author.to_label}/)
203
306
  end
204
307
  end
205
308
 
206
309
  it 'should have one option with a "selected" attribute (bob)' do
207
- output_buffer.should have_tag("form li select[@name='post[author_id]'] option[@selected]", :count => 1)
310
+ expect(output_buffer.to_str).to have_tag("form li select[@name='post[author_id]'] option[@selected]", :count => 1)
208
311
  end
209
312
 
210
313
  it 'should not singularize the association name' do
211
- @new_post.stub(:author_status).and_return(@bob)
212
- @new_post.stub(:author_status_id).and_return(@bob.id)
213
- @new_post.stub(:column_for_attribute).and_return(double('column', :type => :integer, :limit => 255))
314
+ allow(@new_post).to receive(:author_status).and_return(@bob)
315
+ allow(@new_post).to receive(:author_status_id).and_return(@bob.id)
316
+ allow(@new_post).to receive(:column_for_attribute).and_return(double('column', :type => :integer, :limit => 255))
214
317
 
215
318
  concat(semantic_form_for(@new_post) do |builder|
216
319
  concat(builder.input(:author_status, :as => :select))
217
320
  end)
218
321
 
219
- output_buffer.should have_tag('form li select#post_author_status_id')
322
+ expect(output_buffer.to_str).to have_tag('form li select#post_author_status_id')
220
323
  end
221
324
  end
222
325
 
223
326
  describe "for a belongs_to association with :conditions" do
224
327
  before do
225
- ::Post.stub(:reflect_on_association).with(:author).and_return do
226
- mock = double('reflection', :options => {:conditions => {:active => true}}, :klass => ::Author, :macro => :belongs_to)
227
- mock.stub(:[]).with(:class_name).and_return("Author")
328
+ allow(::Post).to receive(:reflect_on_association).with(:author) do
329
+ mock = double('reflection', :scope => nil, :options => {:conditions => {:active => true}}, :klass => ::Author, :macro => :belongs_to)
330
+ allow(mock).to receive(:[]).with(:class_name).and_return("Author")
228
331
  mock
229
332
  end
230
333
  end
231
334
 
232
- it "should call author.(scoped|where) with association conditions" do
233
- if Formtastic::Util.rails3?
234
- ::Author.should_receive(:scoped).with(:conditions => {:active => true})
235
- else
236
- ::Author.should_receive(:where).with({:active => true})
237
- end
335
+ it "should call author.where with association conditions" do
336
+ expect(::Author).to receive(:where).with({:active => true})
238
337
 
239
338
  semantic_form_for(@new_post) do |builder|
240
339
  concat(builder.input(:author, :as => :select))
241
340
  end
242
341
  end
342
+ end
243
343
 
244
- it "should call author.(scoped|where) with association conditions" do
245
- if Formtastic::Util.rails3?
246
- ::Author.should_receive(:scoped).with(:conditions => {:active => true})
247
- else
248
- ::Author.should_receive(:where).with({:active => true})
344
+ describe "for a belongs_to association with scope" do
345
+ before do
346
+ @active_scope = -> { active }
347
+ allow(::Post).to receive(:reflect_on_association).with(:author) do
348
+ mock = double('reflection', :scope => @active_scope, options: {}, :klass => ::Author, :macro => :belongs_to)
349
+ allow(mock).to receive(:[]).with(:class_name).and_return("Author")
350
+ mock
249
351
  end
352
+ end
353
+
354
+ it "should call author.merge with association scope" do
355
+ expect(::Author).to receive(:merge).with(@active_scope)
356
+
250
357
  semantic_form_for(@new_post) do |builder|
251
358
  concat(builder.input(:author, :as => :select))
252
359
  end
@@ -269,31 +376,31 @@ describe 'select input' do
269
376
  it_should_use_the_collection_when_provided(:select, 'option')
270
377
 
271
378
  it 'should have a select inside the wrapper' do
272
- output_buffer.should have_tag('form li select')
273
- output_buffer.should have_tag('form li select#author_post_ids')
379
+ expect(output_buffer.to_str).to have_tag('form li select')
380
+ expect(output_buffer.to_str).to have_tag('form li select#author_post_ids')
274
381
  end
275
382
 
276
383
  it 'should have a multi-select select' do
277
- output_buffer.should have_tag('form li select[@multiple="multiple"]')
384
+ expect(output_buffer.to_str).to have_tag('form li select[@multiple="multiple"]')
278
385
  end
279
-
386
+
280
387
  it 'should append [] to the name attribute for multiple select' do
281
- output_buffer.should have_tag('form li select[@multiple="multiple"][@name="author[post_ids][]"]')
388
+ expect(output_buffer.to_str).to have_tag('form li select[@multiple="multiple"][@name="author[post_ids][]"]')
282
389
  end
283
390
 
284
391
  it 'should have a hidden field' do
285
- output_buffer.should have_tag('form li input[@type="hidden"][@name="author[post_ids][]"]', :count => 1)
392
+ expect(output_buffer.to_str).to have_tag('form li input[@type="hidden"][@name="author[post_ids][]"]', :count => 1)
286
393
  end
287
394
 
288
395
  it 'should have a select option for each Post' do
289
- output_buffer.should have_tag('form li select option', :count => ::Post.all.size)
396
+ expect(output_buffer.to_str).to have_tag('form li select option', :count => ::Post.all.size)
290
397
  ::Post.all.each do |post|
291
- output_buffer.should have_tag("form li select option[@value='#{post.id}']", /#{post.to_label}/)
398
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='#{post.id}']", :text => /#{post.to_label}/)
292
399
  end
293
400
  end
294
401
 
295
402
  it 'should not have a blank option by default' do
296
- output_buffer.should_not have_tag("form li select option[@value='']")
403
+ expect(output_buffer.to_str).not_to have_tag("form li select option[@value='']")
297
404
  end
298
405
 
299
406
  it 'should respect the :include_blank option for single selects' do
@@ -301,7 +408,7 @@ describe 'select input' do
301
408
  concat(builder.input(:posts, :as => :select, :multiple => false, :include_blank => true))
302
409
  end)
303
410
 
304
- output_buffer.should have_tag("form li select option[@value='']")
411
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='']")
305
412
  end
306
413
 
307
414
  it 'should respect the :include_blank option for multiple selects' do
@@ -309,11 +416,11 @@ describe 'select input' do
309
416
  concat(builder.input(:posts, :as => :select, :multiple => true, :include_blank => true))
310
417
  end)
311
418
 
312
- output_buffer.should have_tag("form li select option[@value='']")
419
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='']")
313
420
  end
314
421
 
315
422
  it 'should have one option with a "selected" attribute' do
316
- output_buffer.should have_tag('form li select option[@selected]', :count => 1)
423
+ expect(output_buffer.to_str).to have_tag('form li select option[@selected]', :count => 1)
317
424
  end
318
425
  end
319
426
 
@@ -333,23 +440,23 @@ describe 'select input' do
333
440
  it_should_use_the_collection_when_provided(:select, 'option')
334
441
 
335
442
  it 'should have a select inside the wrapper' do
336
- output_buffer.should have_tag('form li select')
337
- output_buffer.should have_tag('form li select#post_author_ids')
443
+ expect(output_buffer.to_str).to have_tag('form li select')
444
+ expect(output_buffer.to_str).to have_tag('form li select#post_author_ids')
338
445
  end
339
446
 
340
447
  it 'should have a multi-select select' do
341
- output_buffer.should have_tag('form li select[@multiple="multiple"]')
448
+ expect(output_buffer.to_str).to have_tag('form li select[@multiple="multiple"]')
342
449
  end
343
450
 
344
451
  it 'should have a select option for each Author' do
345
- output_buffer.should have_tag('form li select option', :count => ::Author.all.size)
452
+ expect(output_buffer.to_str).to have_tag('form li select option', :count => ::Author.all.size)
346
453
  ::Author.all.each do |author|
347
- output_buffer.should have_tag("form li select option[@value='#{author.id}']", /#{author.to_label}/)
454
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='#{author.id}']", :text => /#{author.to_label}/)
348
455
  end
349
456
  end
350
457
 
351
458
  it 'should not have a blank option by default' do
352
- output_buffer.should_not have_tag("form li select option[@value='']")
459
+ expect(output_buffer.to_str).not_to have_tag("form li select option[@value='']")
353
460
  end
354
461
 
355
462
  it 'should respect the :include_blank option for single selects' do
@@ -357,7 +464,7 @@ describe 'select input' do
357
464
  concat(builder.input(:authors, :as => :select, :multiple => false, :include_blank => true))
358
465
  end)
359
466
 
360
- output_buffer.should have_tag("form li select option[@value='']")
467
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='']")
361
468
  end
362
469
 
363
470
  it 'should respect the :include_blank option for multiple selects' do
@@ -365,51 +472,51 @@ describe 'select input' do
365
472
  concat(builder.input(:authors, :as => :select, :multiple => true, :include_blank => true))
366
473
  end)
367
474
 
368
- output_buffer.should have_tag("form li select option[@value='']")
475
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='']")
369
476
  end
370
477
 
371
478
  it 'should have one option with a "selected" attribute' do
372
- output_buffer.should have_tag('form li select option[@selected]', :count => 1)
479
+ expect(output_buffer.to_str).to have_tag('form li select option[@selected]', :count => 1)
373
480
  end
374
481
  end
375
482
 
376
483
  describe 'when :prompt => "choose something" is set' do
377
484
  before do
378
- @new_post.stub(:author_id).and_return(nil)
485
+ allow(@new_post).to receive(:author_id).and_return(nil)
379
486
  concat(semantic_form_for(@new_post) do |builder|
380
487
  concat(builder.input(:author, :as => :select, :prompt => "choose author"))
381
488
  end)
382
489
  end
383
490
 
384
491
  it 'should have a select with prompt' do
385
- output_buffer.should have_tag("form li select option[@value='']", /choose author/, :count => 1)
492
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='']", :text => /choose author/, :count => 1)
386
493
  end
387
494
 
388
495
  it 'should not have a second blank select option' do
389
- output_buffer.should have_tag("form li select option[@value='']", :count => 1)
496
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='']", :count => 1)
390
497
  end
391
498
  end
392
499
 
393
500
  describe 'when no object is given' do
394
- before(:each) do
501
+ before(:example) do
395
502
  concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
396
503
  concat(builder.input(:author, :as => :select, :collection => ::Author.all))
397
504
  end)
398
505
  end
399
506
 
400
507
  it 'should generate label' do
401
- output_buffer.should have_tag('form li label', /Author/)
402
- output_buffer.should have_tag("form li label[@for='project_author']")
508
+ expect(output_buffer.to_str).to have_tag('form li label', :text => /Author/)
509
+ expect(output_buffer.to_str).to have_tag("form li label[@for='project_author']")
403
510
  end
404
511
 
405
512
  it 'should generate select inputs' do
406
- output_buffer.should have_tag('form li select#project_author')
407
- output_buffer.should have_tag('form li select option', :count => ::Author.all.size + 1)
513
+ expect(output_buffer.to_str).to have_tag('form li select#project_author')
514
+ expect(output_buffer.to_str).to have_tag('form li select option', :count => ::Author.all.size + 1)
408
515
  end
409
516
 
410
517
  it 'should generate an option to each item' do
411
518
  ::Author.all.each do |author|
412
- output_buffer.should have_tag("form li select option[@value='#{author.id}']", /#{author.to_label}/)
519
+ expect(output_buffer.to_str).to have_tag("form li select option[@value='#{author.id}']", :text => /#{author.to_label}/)
413
520
  end
414
521
  end
415
522
  end
@@ -420,7 +527,7 @@ describe 'select input' do
420
527
  concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
421
528
  concat(builder.input(:author_name, :as => :select, :collection => ::Author.all))
422
529
  end)
423
- output_buffer.should have_tag("form li select[@name='project[author_name]']")
530
+ expect(output_buffer.to_str).to have_tag("form li select[@name='project[author_name]']")
424
531
  end
425
532
 
426
533
  describe 'and :multiple is set to true through :input_html' do
@@ -428,7 +535,7 @@ describe 'select input' do
428
535
  concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
429
536
  concat(builder.input(:author_name, :as => :select, :input_html => {:multiple => true} ))
430
537
  end)
431
- output_buffer.should have_tag("form li select[@multiple]")
538
+ expect(output_buffer.to_str).to have_tag("form li select[@multiple]")
432
539
  end
433
540
  end
434
541
 
@@ -437,14 +544,14 @@ describe 'select input' do
437
544
  concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
438
545
  concat(builder.input(:author_name, :as => :select, :multiple => true, :collection => ["Fred", "Bob"]))
439
546
  end)
440
- output_buffer.should have_tag("form li select[@multiple]")
547
+ expect(output_buffer.to_str).to have_tag("form li select[@multiple]")
441
548
  end
442
549
  end
443
550
 
444
551
  end
445
552
 
446
553
  describe 'when a grouped collection collection is given' do
447
- before(:each) do
554
+ before(:example) do
448
555
  concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
449
556
  @grouped_opts = [['one', ['pencil', 'crayon', 'pen']],
450
557
  ['two', ['eyes', 'hands', 'feet']],
@@ -455,20 +562,20 @@ describe 'select input' do
455
562
 
456
563
  it 'should generate an option to each item' do
457
564
  @grouped_opts.each do |opt_pair|
458
- output_buffer.should have_tag("form li select optgroup[@label='#{opt_pair[0]}']")
565
+ expect(output_buffer.to_str).to have_tag("form li select optgroup[@label='#{opt_pair[0]}']")
459
566
  opt_pair[1].each do |v|
460
- output_buffer.should have_tag("form li select optgroup[@label='#{opt_pair[0]}'] option[@value='#{v}']")
567
+ expect(output_buffer.to_str).to have_tag("form li select optgroup[@label='#{opt_pair[0]}'] option[@value='#{v}']")
461
568
  end
462
569
  end
463
- output_buffer.should have_tag("form li select optgroup option[@selected]","hands")
570
+ expect(output_buffer.to_str).to have_tag("form li select optgroup option[@selected]","hands")
464
571
  end
465
572
  end
466
573
 
467
574
  describe "enum" do
468
575
  before do
469
- @output_buffer = ''
576
+ @output_buffer = ActionView::OutputBuffer.new ''
470
577
  @some_meta_descriptions = ["One", "Two", "Three"]
471
- @new_post.stub(:meta_description).at_least(:once)
578
+ allow(@new_post).to receive(:meta_description).at_least(:once)
472
579
  end
473
580
 
474
581
  describe ":as is not set" do
@@ -482,7 +589,7 @@ describe 'select input' do
482
589
  end
483
590
 
484
591
  it "should render a select field" do
485
- output_buffer.should have_tag("form li select", :count => 2)
592
+ expect(output_buffer.to_str).to have_tag("form li select", :count => 2)
486
593
  end
487
594
  end
488
595
 
@@ -498,7 +605,7 @@ describe 'select input' do
498
605
  end
499
606
 
500
607
  it "should render a text field" do
501
- output_buffer.should have_tag("form li input[@type='text']", :count => 2)
608
+ expect(output_buffer.to_str).to have_tag("form li input[@type='text']", :count => 2)
502
609
  end
503
610
  end
504
611
  end
@@ -513,32 +620,32 @@ describe 'select input' do
513
620
  it_should_have_select_with_id("context2_post_author_ids")
514
621
  it_should_have_label_for("context2_post_author_ids")
515
622
  end
516
-
623
+
517
624
  describe "when index is provided" do
518
-
625
+
519
626
  before do
520
- @output_buffer = ''
627
+ @output_buffer = ActionView::OutputBuffer.new ''
521
628
  mock_everything
522
-
629
+
523
630
  concat(semantic_form_for(@new_post) do |builder|
524
631
  concat(builder.fields_for(:author, :index => 3) do |author|
525
632
  concat(author.input(:name, :as => :select))
526
633
  end)
527
634
  end)
528
635
  end
529
-
636
+
530
637
  it 'should index the id of the wrapper' do
531
- output_buffer.should have_tag("li#post_author_attributes_3_name_input")
638
+ expect(output_buffer.to_str).to have_tag("li#post_author_attributes_3_name_input")
532
639
  end
533
-
640
+
534
641
  it 'should index the id of the select tag' do
535
- output_buffer.should have_tag("select#post_author_attributes_3_name")
642
+ expect(output_buffer.to_str).to have_tag("select#post_author_attributes_3_name")
536
643
  end
537
-
644
+
538
645
  it 'should index the name of the select' do
539
- output_buffer.should have_tag("select[@name='post[author_attributes][3][name]']")
646
+ expect(output_buffer.to_str).to have_tag("select[@name='post[author_attributes][3][name]']")
540
647
  end
541
-
648
+
542
649
  end
543
650
 
544
651
  context "when required" do
@@ -547,7 +654,7 @@ describe 'select input' do
547
654
  concat(semantic_form_for(@new_post) do |builder|
548
655
  concat(builder.input(:author, :as => :select, :required => true))
549
656
  end)
550
- output_buffer.should have_tag("select[@required]")
657
+ expect(output_buffer.to_str).to have_tag("select[@required]")
551
658
  end
552
659
  end
553
660
  end