formtastic 2.1.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,31 +1,23 @@
1
1
  # encoding: utf-8
2
2
  require 'spec_helper'
3
3
 
4
- describe 'Formtastic::FormBuilder#input' do
5
-
6
- include FormtasticSpecHelper
4
+ RSpec.describe 'with input class finder' do
5
+ include_context 'form builder'
7
6
 
8
7
  before do
9
- @output_buffer = ''
10
- mock_everything
11
-
12
- @errors = mock('errors')
13
- @errors.stub!(:[]).and_return([])
14
- @new_post.stub!(:errors).and_return(@errors)
15
- end
16
-
17
- after do
18
- ::I18n.backend.reload!
8
+ @errors = double('errors')
9
+ allow(@errors).to receive(:[]).and_return([])
10
+ allow(@new_post).to receive(:errors).and_return(@errors)
19
11
  end
20
12
 
21
13
  describe 'arguments and options' do
22
14
 
23
15
  it 'should require the first argument (the method on form\'s object)' do
24
- lambda {
16
+ expect {
25
17
  concat(semantic_form_for(@new_post) do |builder|
26
18
  concat(builder.input()) # no args passed in at all
27
19
  end)
28
- }.should raise_error(ArgumentError)
20
+ }.to raise_error(ArgumentError)
29
21
  end
30
22
 
31
23
  describe ':required option' do
@@ -37,8 +29,8 @@ describe 'Formtastic::FormBuilder#input' do
37
29
  concat(semantic_form_for(@new_post) do |builder|
38
30
  concat(builder.input(:title, :required => true))
39
31
  end)
40
- output_buffer.should_not have_tag('form li.optional')
41
- output_buffer.should have_tag('form li.required')
32
+ expect(output_buffer).not_to have_tag('form li.optional')
33
+ expect(output_buffer).to have_tag('form li.required')
42
34
  end
43
35
  end
44
36
 
@@ -47,7 +39,7 @@ describe 'Formtastic::FormBuilder#input' do
47
39
  concat(semantic_form_for(@new_post) do |builder|
48
40
  concat(builder.input(:title, :required => true))
49
41
  end)
50
- output_buffer.should have_tag('form li.required label', /required yo/)
42
+ expect(output_buffer).to have_tag('form li.required label', :text => /required yo/)
51
43
  end
52
44
  end
53
45
  end
@@ -56,7 +48,7 @@ describe 'Formtastic::FormBuilder#input' do
56
48
 
57
49
  before do
58
50
  @string = Formtastic::FormBuilder.optional_string = " optional yo!" # ensure there's something in the string
59
- @new_post.class.should_not_receive(:reflect_on_all_validations)
51
+ expect(@new_post.class).not_to receive(:reflect_on_all_validations)
60
52
  end
61
53
 
62
54
  after do
@@ -67,26 +59,26 @@ describe 'Formtastic::FormBuilder#input' do
67
59
  concat(semantic_form_for(@new_post) do |builder|
68
60
  concat(builder.input(:title, :required => false))
69
61
  end)
70
- output_buffer.should_not have_tag('form li.required')
71
- output_buffer.should have_tag('form li.optional')
62
+ expect(output_buffer).not_to have_tag('form li.required')
63
+ expect(output_buffer).to have_tag('form li.optional')
72
64
  end
73
65
 
74
66
  it 'should set and "optional" class also when there is presence validator' do
75
- @new_post.class.should_receive(:validators_on).with(:title).any_number_of_times.and_return([
76
- active_model_presence_validator([:title])
77
- ])
67
+ expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
68
+ active_model_presence_validator([:title])
69
+ ])
78
70
  concat(semantic_form_for(@new_post) do |builder|
79
71
  concat(builder.input(:title, :required => false))
80
72
  end)
81
- output_buffer.should_not have_tag('form li.required')
82
- output_buffer.should have_tag('form li.optional')
73
+ expect(output_buffer).not_to have_tag('form li.required')
74
+ expect(output_buffer).to have_tag('form li.optional')
83
75
  end
84
76
 
85
77
  it 'should append the "optional" string to the label' do
86
78
  concat(semantic_form_for(@new_post) do |builder|
87
79
  concat(builder.input(:title, :required => false))
88
80
  end)
89
- output_buffer.should have_tag('form li.optional label', /#{@string}$/)
81
+ expect(output_buffer).to have_tag('form li.optional label', :text => /#{@string}$/)
90
82
  end
91
83
 
92
84
  end
@@ -96,14 +88,14 @@ describe 'Formtastic::FormBuilder#input' do
96
88
  describe 'and an object was not given' do
97
89
 
98
90
  it 'should use the default value' do
99
- Formtastic::FormBuilder.all_fields_required_by_default.should == true
91
+ expect(Formtastic::FormBuilder.all_fields_required_by_default).to eq(true)
100
92
  Formtastic::FormBuilder.all_fields_required_by_default = false
101
93
 
102
94
  concat(semantic_form_for(:project, :url => 'http://test.host/') do |builder|
103
95
  concat(builder.input(:title))
104
96
  end)
105
- output_buffer.should_not have_tag('form li.required')
106
- output_buffer.should have_tag('form li.optional')
97
+ expect(output_buffer).not_to have_tag('form li.required')
98
+ expect(output_buffer).to have_tag('form li.optional')
107
99
 
108
100
  Formtastic::FormBuilder.all_fields_required_by_default = true
109
101
  end
@@ -112,90 +104,151 @@ describe 'Formtastic::FormBuilder#input' do
112
104
 
113
105
  describe 'and an object with :validators_on was given (ActiveModel, Active Resource)' do
114
106
  before do
115
- @new_post.stub!(:class).and_return(::PostModel)
107
+ allow(@new_post).to receive(:class).and_return(::PostModel)
116
108
  end
117
109
 
118
110
  after do
119
- @new_post.stub!(:class).and_return(::Post)
111
+ allow(@new_post).to receive(:class).and_return(::Post)
120
112
  end
121
113
  describe 'and validates_presence_of was called for the method' do
122
114
  it 'should be required' do
123
115
 
124
- @new_post.class.should_receive(:validators_on).with(:title).any_number_of_times.and_return([
125
- active_model_presence_validator([:title])
126
- ])
116
+ expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
117
+ active_model_presence_validator([:title])
118
+ ])
127
119
 
128
- @new_post.class.should_receive(:validators_on).with(:body).any_number_of_times.and_return([
129
- active_model_presence_validator([:body], {:if => true})
130
- ])
120
+ expect(@new_post.class).to receive(:validators_on).with(:body).at_least(:once).and_return([
121
+ active_model_presence_validator([:body], {:if => true})
122
+ ])
131
123
 
132
124
  concat(semantic_form_for(@new_post) do |builder|
133
125
  concat(builder.input(:title))
134
126
  concat(builder.input(:body))
135
127
  end)
136
- output_buffer.should have_tag('form li.required')
137
- output_buffer.should_not have_tag('form li.optional')
128
+ expect(output_buffer).to have_tag('form li.required')
129
+ expect(output_buffer).not_to have_tag('form li.optional')
138
130
  end
139
131
 
140
132
  it 'should be required when there is :on => :create option on create' do
141
133
  with_config :required_string, " required yo!" do
142
- @new_post.class.should_receive(:validators_on).with(:title).any_number_of_times.and_return([
143
- active_model_presence_validator([:title], {:on => :create})
144
- ])
134
+ expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
135
+ active_model_presence_validator([:title], {:on => :create})
136
+ ])
137
+ concat(semantic_form_for(@new_post) do |builder|
138
+ concat(builder.input(:title))
139
+ end)
140
+ expect(output_buffer).to have_tag('form li.required')
141
+ expect(output_buffer).not_to have_tag('form li.optional')
142
+ end
143
+ end
144
+
145
+ it 'should be required when there is :create option in validation contexts array on create' do
146
+ with_config :required_string, " required yo!" do
147
+ expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
148
+ active_model_presence_validator([:title], {:on => [:create]})
149
+ ])
145
150
  concat(semantic_form_for(@new_post) do |builder|
146
151
  concat(builder.input(:title))
147
152
  end)
148
- output_buffer.should have_tag('form li.required')
149
- output_buffer.should_not have_tag('form li.optional')
153
+ expect(output_buffer).to have_tag('form li.required')
154
+ expect(output_buffer).not_to have_tag('form li.optional')
150
155
  end
151
156
  end
152
157
 
153
158
  it 'should be required when there is :on => :save option on create' do
154
159
  with_config :required_string, " required yo!" do
155
- @new_post.class.should_receive(:validators_on).with(:title).any_number_of_times.and_return([
156
- active_model_presence_validator([:title], {:on => :save})
157
- ])
160
+ expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
161
+ active_model_presence_validator([:title], {:on => :save})
162
+ ])
158
163
  concat(semantic_form_for(@new_post) do |builder|
159
164
  concat(builder.input(:title))
160
165
  end)
161
- output_buffer.should have_tag('form li.required')
162
- output_buffer.should_not have_tag('form li.optional')
166
+ expect(output_buffer).to have_tag('form li.required')
167
+ expect(output_buffer).not_to have_tag('form li.optional')
168
+ end
169
+ end
170
+
171
+ it 'should be required when there is :save option in validation contexts array on create' do
172
+ with_config :required_string, " required yo!" do
173
+ expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
174
+ active_model_presence_validator([:title], {:on => [:save]})
175
+ ])
176
+ concat(semantic_form_for(@new_post) do |builder|
177
+ concat(builder.input(:title))
178
+ end)
179
+ expect(output_buffer).to have_tag('form li.required')
180
+ expect(output_buffer).not_to have_tag('form li.optional')
163
181
  end
164
182
  end
165
183
 
166
184
  it 'should be required when there is :on => :save option on update' do
167
185
  with_config :required_string, " required yo!" do
168
- @fred.class.should_receive(:validators_on).with(:login).any_number_of_times.and_return([
169
- active_model_presence_validator([:login], {:on => :save})
170
- ])
186
+ expect(@fred.class).to receive(:validators_on).with(:login).at_least(:once).and_return([
187
+ active_model_presence_validator([:login], {:on => :save})
188
+ ])
189
+ concat(semantic_form_for(@fred) do |builder|
190
+ concat(builder.input(:login))
191
+ end)
192
+ expect(output_buffer).to have_tag('form li.required')
193
+ expect(output_buffer).not_to have_tag('form li.optional')
194
+ end
195
+ end
196
+
197
+ it 'should be required when there is :save option in validation contexts array on update' do
198
+ with_config :required_string, " required yo!" do
199
+ expect(@fred.class).to receive(:validators_on).with(:login).at_least(:once).and_return([
200
+ active_model_presence_validator([:login], {:on => [:save]})
201
+ ])
171
202
  concat(semantic_form_for(@fred) do |builder|
172
203
  concat(builder.input(:login))
173
204
  end)
174
- output_buffer.should have_tag('form li.required')
175
- output_buffer.should_not have_tag('form li.optional')
205
+ expect(output_buffer).to have_tag('form li.required')
206
+ expect(output_buffer).not_to have_tag('form li.optional')
176
207
  end
177
208
  end
178
209
 
179
210
  it 'should not be required when there is :on => :create option on update' do
180
- @fred.class.should_receive(:validators_on).with(:login).any_number_of_times.and_return([
181
- active_model_presence_validator([:login], {:on => :create})
182
- ])
211
+ expect(@fred.class).to receive(:validators_on).with(:login).at_least(:once).and_return([
212
+ active_model_presence_validator([:login], {:on => :create})
213
+ ])
214
+ concat(semantic_form_for(@fred) do |builder|
215
+ concat(builder.input(:login))
216
+ end)
217
+ expect(output_buffer).not_to have_tag('form li.required')
218
+ expect(output_buffer).to have_tag('form li.optional')
219
+ end
220
+
221
+ it 'should not be required when there is :create option in validation contexts array on update' do
222
+ expect(@fred.class).to receive(:validators_on).with(:login).at_least(:once).and_return([
223
+ active_model_presence_validator([:login], {:on => [:create]})
224
+ ])
183
225
  concat(semantic_form_for(@fred) do |builder|
184
226
  concat(builder.input(:login))
185
227
  end)
186
- output_buffer.should_not have_tag('form li.required')
187
- output_buffer.should have_tag('form li.optional')
228
+ expect(output_buffer).not_to have_tag('form li.required')
229
+ expect(output_buffer).to have_tag('form li.optional')
188
230
  end
189
231
 
190
232
  it 'should not be required when there is :on => :update option on create' do
191
- @new_post.class.should_receive(:validators_on).with(:title).any_number_of_times.and_return([
192
- active_model_presence_validator([:title], {:on => :update})
193
- ])
233
+ expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
234
+ active_model_presence_validator([:title], {:on => :update})
235
+ ])
236
+ concat(semantic_form_for(@new_post) do |builder|
237
+ concat(builder.input(:title))
238
+ end)
239
+ expect(output_buffer).not_to have_tag('form li.required')
240
+ expect(output_buffer).to have_tag('form li.optional')
241
+ end
242
+
243
+ it 'should not be required when there is :update option in validation contexts array on create' do
244
+ expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
245
+ active_model_presence_validator([:title], {:on => [:update]})
246
+ ])
194
247
  concat(semantic_form_for(@new_post) do |builder|
195
248
  concat(builder.input(:title))
196
249
  end)
197
- output_buffer.should_not have_tag('form li.required')
198
- output_buffer.should have_tag('form li.optional')
250
+ expect(output_buffer).not_to have_tag('form li.required')
251
+ expect(output_buffer).to have_tag('form li.optional')
199
252
  end
200
253
 
201
254
  it 'should be not be required if the optional :if condition is not satisifed' do
@@ -219,38 +272,38 @@ describe 'Formtastic::FormBuilder#input' do
219
272
  end
220
273
 
221
274
  it 'should be required if the optional :if with a method string evaluates to true' do
222
- @new_post.should_receive(:required_condition).and_return(true)
275
+ expect(@new_post).to receive(:required_condition).and_return(true)
223
276
  presence_should_be_required(:required => true, :tag => :body, :options => { :if => :required_condition })
224
277
  end
225
278
 
226
279
  it 'should be required if the optional :if with a method string evaluates to false' do
227
- @new_post.should_receive(:required_condition).and_return(false)
280
+ expect(@new_post).to receive(:required_condition).and_return(false)
228
281
  presence_should_be_required(:required => false, :tag => :body, :options => { :if => :required_condition })
229
282
  end
230
283
 
231
284
  it 'should be required if the optional :unless with a method string evaluates to false' do
232
- @new_post.should_receive(:required_condition).and_return(false)
285
+ expect(@new_post).to receive(:required_condition).and_return(false)
233
286
  presence_should_be_required(:required => true, :tag => :body, :options => { :unless => :required_condition })
234
287
  end
235
288
 
236
- it 'should not be required if the optional :unless with a method string evaluates to true' do
237
- @new_post.should_receive(:required_condition).and_return(true)
238
- presence_should_be_required(:required => false, :tag => :body, :options => { :unless => :required_condition })
239
- end
289
+ it 'should not be required if the optional :unless with a method string evaluates to true' do
290
+ expect(@new_post).to receive(:required_condition).and_return(true)
291
+ presence_should_be_required(:required => false, :tag => :body, :options => { :unless => :required_condition })
292
+ end
240
293
  end
241
294
 
242
295
  describe 'and validates_inclusion_of was called for the method' do
243
296
  it 'should be required' do
244
- @new_post.class.should_receive(:validators_on).with(:published).any_number_of_times.and_return([
245
- active_model_inclusion_validator([:published], {:in => [false, true]})
246
- ])
297
+ expect(@new_post.class).to receive(:validators_on).with(:published).at_least(:once).and_return([
298
+ active_model_inclusion_validator([:published], {:in => [false, true]})
299
+ ])
247
300
  should_be_required(:tag => :published, :required => true)
248
301
  end
249
302
 
250
303
  it 'should not be required if allow_blank is true' do
251
- @new_post.class.should_receive(:validators_on).with(:published).any_number_of_times.and_return([
252
- active_model_inclusion_validator([:published], {:in => [false, true], :allow_blank => true})
253
- ])
304
+ expect(@new_post.class).to receive(:validators_on).with(:published).at_least(:once).and_return([
305
+ active_model_inclusion_validator([:published], {:in => [false, true], :allow_blank => true})
306
+ ])
254
307
  should_be_required(:tag => :published, :required => false)
255
308
  end
256
309
  end
@@ -282,14 +335,14 @@ describe 'Formtastic::FormBuilder#input' do
282
335
  end
283
336
 
284
337
  def add_presence_validator(options)
285
- @new_post.class.stub!(:validators_on).with(options[:tag]).and_return([
286
- active_model_presence_validator([options[:tag]], options[:options])
287
- ])
338
+ allow(@new_post.class).to receive(:validators_on).with(options[:tag]).and_return([
339
+ active_model_presence_validator([options[:tag]], options[:options])
340
+ ])
288
341
  end
289
342
 
290
343
  def add_length_validator(options)
291
- @new_post.class.should_receive(:validators_on).with(options[:tag]).any_number_of_times {[
292
- active_model_length_validator([options[:tag]], options[:options])
344
+ expect(@new_post.class).to receive(:validators_on).with(options[:tag]).at_least(:once) {[
345
+ active_model_length_validator([options[:tag]], options[:options])
293
346
  ]}
294
347
  end
295
348
 
@@ -300,11 +353,11 @@ describe 'Formtastic::FormBuilder#input' do
300
353
  end)
301
354
 
302
355
  if options[:required]
303
- output_buffer.should_not have_tag('form li.optional')
304
- output_buffer.should have_tag('form li.required')
356
+ expect(output_buffer).not_to have_tag('form li.optional')
357
+ expect(output_buffer).to have_tag('form li.required')
305
358
  else
306
- output_buffer.should have_tag('form li.optional')
307
- output_buffer.should_not have_tag('form li.required')
359
+ expect(output_buffer).to have_tag('form li.optional')
360
+ expect(output_buffer).not_to have_tag('form li.required')
308
361
  end
309
362
  end
310
363
 
@@ -321,15 +374,15 @@ describe 'Formtastic::FormBuilder#input' do
321
374
  # TODO JF reversed this during refactor, need to make sure
322
375
  describe 'and there are no requirement validations on the method' do
323
376
  before do
324
- @new_post.class.should_receive(:validators_on).with(:title).and_return([])
377
+ expect(@new_post.class).to receive(:validators_on).with(:title).and_return([])
325
378
  end
326
379
 
327
380
  it 'should not be required' do
328
381
  concat(semantic_form_for(@new_post) do |builder|
329
382
  concat(builder.input(:title))
330
383
  end)
331
- output_buffer.should_not have_tag('form li.required')
332
- output_buffer.should have_tag('form li.optional')
384
+ expect(output_buffer).not_to have_tag('form li.required')
385
+ expect(output_buffer).to have_tag('form li.optional')
333
386
  end
334
387
  end
335
388
 
@@ -337,21 +390,21 @@ describe 'Formtastic::FormBuilder#input' do
337
390
 
338
391
  describe 'and an object without :validators_on' do
339
392
 
340
- it 'should use the default value' do
341
- Formtastic::FormBuilder.all_fields_required_by_default.should == true
342
- Formtastic::FormBuilder.all_fields_required_by_default = false
343
-
344
- concat(semantic_form_for(@new_post) do |builder|
345
- concat(builder.input(:title))
346
- end)
347
- output_buffer.should_not have_tag('form li.required')
348
- output_buffer.should have_tag('form li.optional')
393
+ it 'should use the default value' do
394
+ expect(Formtastic::FormBuilder.all_fields_required_by_default).to eq(true)
395
+ Formtastic::FormBuilder.all_fields_required_by_default = false
349
396
 
350
- Formtastic::FormBuilder.all_fields_required_by_default = true
351
- end
397
+ concat(semantic_form_for(@new_post) do |builder|
398
+ concat(builder.input(:title))
399
+ end)
400
+ expect(output_buffer).not_to have_tag('form li.required')
401
+ expect(output_buffer).to have_tag('form li.optional')
352
402
 
403
+ Formtastic::FormBuilder.all_fields_required_by_default = true
353
404
  end
354
405
 
406
+ end
407
+
355
408
  end
356
409
 
357
410
  end
@@ -364,7 +417,7 @@ describe 'Formtastic::FormBuilder#input' do
364
417
  concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
365
418
  concat(builder.input(:anything))
366
419
  end)
367
- output_buffer.should have_tag('form li.string')
420
+ expect(output_buffer).to have_tag('form li.string')
368
421
  end
369
422
 
370
423
  it 'should default to password for forms without objects if column is password' do
@@ -373,117 +426,145 @@ describe 'Formtastic::FormBuilder#input' do
373
426
  concat(builder.input(:password_confirmation))
374
427
  concat(builder.input(:confirm_password))
375
428
  end)
376
- output_buffer.should have_tag('form li.password', :count => 3)
429
+ expect(output_buffer).to have_tag('form li.password', :count => 3)
377
430
  end
378
431
 
379
432
  it 'should default to a string for methods on objects that don\'t respond to "column_for_attribute"' do
380
- @new_post.stub!(:method_without_a_database_column)
381
- @new_post.stub!(:column_for_attribute).and_return(nil)
382
- default_input_type(nil, :method_without_a_database_column).should == :string
433
+ allow(@new_post).to receive(:method_without_a_database_column)
434
+ allow(@new_post).to receive(:column_for_attribute).and_return(nil)
435
+ expect(default_input_type(nil, :method_without_a_database_column)).to eq(:string)
383
436
  end
384
437
 
385
438
  it 'should default to :password for methods that don\'t have a column in the database but "password" is in the method name' do
386
- @new_post.stub!(:password_method_without_a_database_column)
387
- @new_post.stub!(:column_for_attribute).and_return(nil)
388
- default_input_type(nil, :password_method_without_a_database_column).should == :password
439
+ allow(@new_post).to receive(:password_method_without_a_database_column)
440
+ allow(@new_post).to receive(:column_for_attribute).and_return(nil)
441
+ expect(default_input_type(nil, :password_method_without_a_database_column)).to eq(:password)
389
442
  end
390
443
 
391
444
  it 'should default to :password for methods on objects that don\'t respond to "column_for_attribute" but "password" is in the method name' do
392
- @new_post.stub!(:password_method_without_a_database_column)
393
- @new_post.stub!(:column_for_attribute).and_return(nil)
394
- default_input_type(nil, :password_method_without_a_database_column).should == :password
445
+ allow(@new_post).to receive(:password_method_without_a_database_column)
446
+ allow(@new_post).to receive(:column_for_attribute).and_return(nil)
447
+ expect(default_input_type(nil, :password_method_without_a_database_column)).to eq(:password)
395
448
  end
396
449
 
397
450
  it 'should default to :number for "integer" column with name ending in "_id"' do
398
- @new_post.stub!(:aws_instance_id)
399
- @new_post.stub!(:column_for_attribute).with(:aws_instance_id).and_return(mock('column', :type => :integer))
400
- default_input_type(:integer, :aws_instance_id).should == :number
451
+ allow(@new_post).to receive(:aws_instance_id)
452
+ allow(@new_post).to receive(:column_for_attribute).with(:aws_instance_id).and_return(double('column', :type => :integer))
453
+ expect(default_input_type(:integer, :aws_instance_id)).to eq(:number)
401
454
  end
402
455
 
403
456
  it 'should default to :select for associations' do
404
- @new_post.class.stub!(:reflect_on_association).with(:user_id).and_return(mock('ActiveRecord::Reflection::AssociationReflection'))
405
- @new_post.class.stub!(:reflect_on_association).with(:section_id).and_return(mock('ActiveRecord::Reflection::AssociationReflection'))
406
- default_input_type(:integer, :user_id).should == :select
407
- default_input_type(:integer, :section_id).should == :select
457
+ allow(@new_post.class).to receive(:reflect_on_association).with(:user_id).and_return(double('ActiveRecord::Reflection::AssociationReflection'))
458
+ allow(@new_post.class).to receive(:reflect_on_association).with(:section_id).and_return(double('ActiveRecord::Reflection::AssociationReflection'))
459
+ expect(default_input_type(:integer, :user_id)).to eq(:select)
460
+ expect(default_input_type(:integer, :section_id)).to eq(:select)
461
+ end
462
+
463
+ it 'should default to :select for enum' do
464
+ statuses = ActiveSupport::HashWithIndifferentAccess.new("active"=>0, "inactive"=>1)
465
+ allow(@new_post.class).to receive(:statuses) { statuses }
466
+ allow(@new_post).to receive(:defined_enums) { {"status" => statuses } }
467
+
468
+ expect(default_input_type(:integer, :status)).to eq(:select)
408
469
  end
409
470
 
410
471
  it 'should default to :password for :string column types with "password" in the method name' do
411
- default_input_type(:string, :password).should == :password
412
- default_input_type(:string, :hashed_password).should == :password
413
- default_input_type(:string, :password_hash).should == :password
472
+ expect(default_input_type(:string, :password)).to eq(:password)
473
+ expect(default_input_type(:string, :hashed_password)).to eq(:password)
474
+ expect(default_input_type(:string, :password_hash)).to eq(:password)
414
475
  end
415
476
 
416
477
  it 'should default to :text for :text column types' do
417
- default_input_type(:text).should == :text
478
+ expect(default_input_type(:text)).to eq(:text)
418
479
  end
419
480
 
420
- it 'should default to :date for :date column types' do
421
- default_input_type(:date).should == :date
481
+ it 'should default to :date_select for :date column types' do
482
+ expect(default_input_type(:date)).to eq(:date_select)
422
483
  end
423
484
 
424
- it 'should default to :datetime for :datetime and :timestamp column types' do
425
- default_input_type(:datetime).should == :datetime
426
- default_input_type(:timestamp).should == :datetime
485
+ it 'should default to :text for :hstore, :json and :jsonb column types' do
486
+ expect(default_input_type(:hstore)).to eq(:text)
487
+ expect(default_input_type(:json)).to eq(:text)
488
+ expect(default_input_type(:jsonb)).to eq(:text)
427
489
  end
428
490
 
429
- it 'should default to :time for :time column types' do
430
- default_input_type(:time).should == :time
491
+ it 'should default to :datetime_select for :datetime and :timestamp column types' do
492
+ expect(default_input_type(:datetime)).to eq(:datetime_select)
493
+ expect(default_input_type(:timestamp)).to eq(:datetime_select)
494
+ end
495
+
496
+ it 'should default to :time_select for :time column types' do
497
+ expect(default_input_type(:time)).to eq(:time_select)
431
498
  end
432
499
 
433
500
  it 'should default to :boolean for :boolean column types' do
434
- default_input_type(:boolean).should == :boolean
501
+ expect(default_input_type(:boolean)).to eq(:boolean)
435
502
  end
436
503
 
437
504
  it 'should default to :string for :string column types' do
438
- default_input_type(:string).should == :string
505
+ expect(default_input_type(:string)).to eq(:string)
506
+ end
507
+
508
+ it 'should default to :string for :citext column types' do
509
+ expect(default_input_type(:citext)).to eq(:string)
510
+ end
511
+
512
+ it 'should default to :string for :inet column types' do
513
+ expect(default_input_type(:inet)).to eq(:string)
439
514
  end
440
515
 
441
516
  it 'should default to :number for :integer, :float and :decimal column types' do
442
- default_input_type(:integer).should == :number
443
- default_input_type(:float).should == :number
444
- default_input_type(:decimal).should == :number
517
+ expect(default_input_type(:integer)).to eq(:number)
518
+ expect(default_input_type(:float)).to eq(:number)
519
+ expect(default_input_type(:decimal)).to eq(:number)
445
520
  end
446
521
 
447
522
  it 'should default to :country for :string columns named country' do
448
- default_input_type(:string, :country).should == :country
523
+ expect(default_input_type(:string, :country)).to eq(:country)
449
524
  end
450
525
 
451
526
  it 'should default to :email for :string columns matching email' do
452
- default_input_type(:string, :email).should == :email
453
- default_input_type(:string, :customer_email).should == :email
454
- default_input_type(:string, :email_work).should == :email
527
+ expect(default_input_type(:string, :email)).to eq(:email)
528
+ expect(default_input_type(:string, :customer_email)).to eq(:email)
529
+ expect(default_input_type(:string, :email_work)).to eq(:email)
455
530
  end
456
531
 
457
532
  it 'should default to :url for :string columns named url or website' do
458
- default_input_type(:string, :url).should == :url
459
- default_input_type(:string, :website).should == :url
460
- default_input_type(:string, :my_url).should == :url
461
- default_input_type(:string, :hurl).should_not == :url
533
+ expect(default_input_type(:string, :url)).to eq(:url)
534
+ expect(default_input_type(:string, :website)).to eq(:url)
535
+ expect(default_input_type(:string, :my_url)).to eq(:url)
536
+ expect(default_input_type(:string, :hurl)).not_to eq(:url)
462
537
  end
463
538
 
464
539
  it 'should default to :phone for :string columns named phone or fax' do
465
- default_input_type(:string, :phone).should == :phone
466
- default_input_type(:string, :fax).should == :phone
540
+ expect(default_input_type(:string, :phone)).to eq(:phone)
541
+ expect(default_input_type(:string, :fax)).to eq(:phone)
467
542
  end
468
543
 
469
544
  it 'should default to :search for :string columns named search' do
470
- default_input_type(:string, :search).should == :search
545
+ expect(default_input_type(:string, :search)).to eq(:search)
546
+ end
547
+
548
+ it 'should default to :color for :string columns matching color' do
549
+ expect(default_input_type(:string, :color)).to eq(:color)
550
+ expect(default_input_type(:string, :user_color)).to eq(:color)
551
+ expect(default_input_type(:string, :color_for_image)).to eq(:color)
471
552
  end
472
553
 
473
554
  describe 'defaulting to file column' do
474
555
  Formtastic::FormBuilder.file_methods.each do |method|
475
556
  it "should default to :file for attributes that respond to ##{method}" do
476
- column = mock('column')
557
+ column = double('column')
477
558
 
478
559
  Formtastic::FormBuilder.file_methods.each do |test|
479
560
  ### TODO: Check if this is ok
480
- column.stub!(method).with(test).and_return(method == test)
561
+ allow(column).to receive(method).with(test).and_return(method == test)
481
562
  end
482
563
 
483
- @new_post.should_receive(method).and_return(column)
564
+ expect(@new_post).to receive(method).and_return(column)
484
565
 
485
566
  semantic_form_for(@new_post) do |builder|
486
- builder.send(:default_input_type, method).should == :file
567
+ expect(builder.send(:default_input_type, method)).to eq(:file)
487
568
  end
488
569
  end
489
570
  end
@@ -492,16 +573,16 @@ describe 'Formtastic::FormBuilder#input' do
492
573
  end
493
574
 
494
575
  it 'should call the corresponding input class with .to_html' do
495
- [:select, :time_zone, :radio, :date, :datetime, :time, :boolean, :check_boxes, :hidden, :string, :password, :number, :text, :file].each do |input_style|
496
- @new_post.stub!(:generic_column_name)
497
- @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
576
+ [:select, :time_zone, :radio, :date_select, :datetime_select, :time_select, :boolean, :check_boxes, :hidden, :string, :password, :number, :text, :file].each do |input_style|
577
+ allow(@new_post).to receive(:generic_column_name)
578
+ allow(@new_post).to receive(:column_for_attribute).and_return(double('column', :type => :string, :limit => 255))
498
579
  semantic_form_for(@new_post) do |builder|
499
- input_instance = mock('Input instance')
580
+ input_instance = double('Input instance')
500
581
  input_class = "#{input_style.to_s}_input".classify
501
582
  input_constant = "Formtastic::Inputs::#{input_class}".constantize
502
583
 
503
- input_constant.should_receive(:new).and_return(input_instance)
504
- input_instance.should_receive(:to_html).and_return("some HTML")
584
+ expect(input_constant).to receive(:new).and_return(input_instance)
585
+ expect(input_instance).to receive(:to_html).and_return("some HTML")
505
586
 
506
587
  concat(builder.input(:generic_column_name, :as => input_style))
507
588
  end
@@ -517,21 +598,21 @@ describe 'Formtastic::FormBuilder#input' do
517
598
  concat(semantic_form_for(@new_post) do |builder|
518
599
  concat(builder.input(:title, :label => "Kustom"))
519
600
  end)
520
- output_buffer.should have_tag("form li label", /Kustom/)
601
+ expect(output_buffer).to have_tag("form li label", :text => /Kustom/)
521
602
  end
522
603
 
523
604
  it 'should not generate a label if false' do
524
605
  concat(semantic_form_for(@new_post) do |builder|
525
606
  concat(builder.input(:title, :label => false))
526
607
  end)
527
- output_buffer.should_not have_tag("form li label")
608
+ expect(output_buffer).not_to have_tag("form li label")
528
609
  end
529
610
 
530
611
  it 'should be dupped if frozen' do
531
612
  concat(semantic_form_for(@new_post) do |builder|
532
613
  concat(builder.input(:title, :label => "Kustom".freeze))
533
614
  end)
534
- output_buffer.should have_tag("form li label", /Kustom/)
615
+ expect(output_buffer).to have_tag("form li label", :text => /Kustom/)
535
616
  end
536
617
  end
537
618
 
@@ -542,18 +623,18 @@ describe 'Formtastic::FormBuilder#input' do
542
623
  it 'should render a label with localized text and not apply the label_str_method' do
543
624
  with_config :label_str_method, :reverse do
544
625
  @localized_label_text = 'Localized title'
545
- @new_post.stub!(:meta_description)
626
+ allow(@new_post).to receive(:meta_description)
546
627
  ::I18n.backend.store_translations :en,
547
- :formtastic => {
548
- :labels => {
549
- :meta_description => @localized_label_text
550
- }
551
- }
628
+ :formtastic => {
629
+ :labels => {
630
+ :meta_description => @localized_label_text
631
+ }
632
+ }
552
633
 
553
634
  concat(semantic_form_for(@new_post) do |builder|
554
635
  concat(builder.input(:meta_description))
555
636
  end)
556
- output_buffer.should have_tag('form li label', /Localized title/)
637
+ expect(output_buffer).to have_tag('form li label', :text => /Localized title/)
557
638
  end
558
639
  end
559
640
  end
@@ -568,32 +649,32 @@ describe 'Formtastic::FormBuilder#input' do
568
649
  concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
569
650
  concat(builder.input(:meta_description))
570
651
  end)
571
- output_buffer.should have_tag("form li label", /#{'meta_description'.humanize}/)
652
+ expect(output_buffer).to have_tag("form li label", :text => /#{'meta_description'.humanize}/)
572
653
  end
573
654
  end
574
655
  end
575
656
 
576
657
  describe 'and object is given' do
577
658
  it 'should delegate the label logic to class human attribute name and pass it down to the label tag' do
578
- @new_post.stub!(:meta_description) # a two word method name
579
- @new_post.class.should_receive(:human_attribute_name).with('meta_description').and_return('meta_description'.humanize)
659
+ allow(@new_post).to receive(:meta_description) # a two word method name
660
+ expect(@new_post.class).to receive(:human_attribute_name).with('meta_description').and_return('meta_description'.humanize)
580
661
 
581
662
  concat(semantic_form_for(@new_post) do |builder|
582
663
  concat(builder.input(:meta_description))
583
664
  end)
584
- output_buffer.should have_tag("form li label", /#{'meta_description'.humanize}/)
665
+ expect(output_buffer).to have_tag("form li label", :text => /#{'meta_description'.humanize}/)
585
666
  end
586
667
  end
587
668
 
588
669
  describe 'and object is given with label_str_method set to :capitalize' do
589
670
  it 'should capitalize method name, passing it down to the label tag' do
590
671
  with_config :label_str_method, :capitalize do
591
- @new_post.stub!(:meta_description)
672
+ allow(@new_post).to receive(:meta_description)
592
673
 
593
674
  concat(semantic_form_for(@new_post) do |builder|
594
675
  concat(builder.input(:meta_description))
595
676
  end)
596
- output_buffer.should have_tag("form li label", /#{'meta_description'.capitalize}/)
677
+ expect(output_buffer).to have_tag("form li label", :text => /#{'meta_description'.capitalize}/)
597
678
  end
598
679
  end
599
680
  end
@@ -604,16 +685,16 @@ describe 'Formtastic::FormBuilder#input' do
604
685
  @localized_label_text = 'Localized title'
605
686
  @default_localized_label_text = 'Default localized title'
606
687
  ::I18n.backend.store_translations :en,
607
- :formtastic => {
608
- :labels => {
609
- :title => @default_localized_label_text,
610
- :published => @default_localized_label_text,
611
- :post => {
612
- :title => @localized_label_text,
613
- :published => @default_localized_label_text
614
- }
615
- }
616
- }
688
+ :formtastic => {
689
+ :labels => {
690
+ :title => @default_localized_label_text,
691
+ :published => @default_localized_label_text,
692
+ :post => {
693
+ :title => @localized_label_text,
694
+ :published => @default_localized_label_text
695
+ }
696
+ }
697
+ }
617
698
  end
618
699
 
619
700
  it 'should render a label with localized label (I18n)' do
@@ -622,26 +703,26 @@ describe 'Formtastic::FormBuilder#input' do
622
703
  concat(builder.input(:title, :label => true))
623
704
  concat(builder.input(:published, :as => :boolean, :label => true))
624
705
  end)
625
- output_buffer.should have_tag('form li label', Regexp.new('^' + @localized_label_text))
706
+ expect(output_buffer).to have_tag('form li label', :text => Regexp.new('^' + @localized_label_text))
626
707
  end
627
708
  end
628
709
 
629
710
  it 'should render a hint paragraph containing an optional localized label (I18n) if first is not set' do
630
711
  with_config :i18n_lookups_by_default, false do
631
712
  ::I18n.backend.store_translations :en,
632
- :formtastic => {
633
- :labels => {
634
- :post => {
635
- :title => nil,
636
- :published => nil
637
- }
638
- }
639
- }
713
+ :formtastic => {
714
+ :labels => {
715
+ :post => {
716
+ :title => nil,
717
+ :published => nil
718
+ }
719
+ }
720
+ }
640
721
  concat(semantic_form_for(@new_post) do |builder|
641
722
  concat(builder.input(:title, :label => true))
642
723
  concat(builder.input(:published, :as => :boolean, :label => true))
643
724
  end)
644
- output_buffer.should have_tag('form li label', Regexp.new('^' + @default_localized_label_text))
725
+ expect(output_buffer).to have_tag('form li label', :text => Regexp.new('^' + @default_localized_label_text))
645
726
  end
646
727
  end
647
728
  end
@@ -662,15 +743,7 @@ describe 'Formtastic::FormBuilder#input' do
662
743
  concat(semantic_form_for(@new_post) do |builder|
663
744
  concat(builder.input(:title, :hint => hint_text))
664
745
  end)
665
- output_buffer.should have_tag("form li p.inline-hints", hint_text)
666
- end
667
-
668
- it 'should have a custom hint class if I ask for one' do
669
- hint_text = "this is the title of the post"
670
- concat(semantic_form_for(@new_post) do |builder|
671
- concat(builder.input(:title, :hint => hint_text, :hint_class => 'custom-hint-class'))
672
- end)
673
- output_buffer.should have_tag("form li p.custom-hint-class", hint_text)
746
+ expect(output_buffer).to have_tag("form li p.inline-hints", :text => hint_text)
674
747
  end
675
748
 
676
749
  it 'should have a custom hint class defaulted for all forms' do
@@ -679,7 +752,7 @@ describe 'Formtastic::FormBuilder#input' do
679
752
  concat(semantic_form_for(@new_post) do |builder|
680
753
  concat(builder.input(:title, :hint => hint_text))
681
754
  end)
682
- output_buffer.should have_tag("form li p.custom-hint-class", hint_text)
755
+ expect(output_buffer).to have_tag("form li p.custom-hint-class", :text => hint_text)
683
756
  end
684
757
  end
685
758
 
@@ -689,11 +762,11 @@ describe 'Formtastic::FormBuilder#input' do
689
762
  @localized_hint_text = "This is the localized hint."
690
763
  @default_localized_hint_text = "This is the default localized hint."
691
764
  ::I18n.backend.store_translations :en,
692
- :formtastic => {
693
- :hints => {
694
- :title => @default_localized_hint_text,
695
- }
696
- }
765
+ :formtastic => {
766
+ :hints => {
767
+ :title => @default_localized_hint_text,
768
+ }
769
+ }
697
770
  end
698
771
 
699
772
  after do
@@ -704,34 +777,17 @@ describe 'Formtastic::FormBuilder#input' do
704
777
  it 'should render a hint paragraph containing a localized hint (I18n)' do
705
778
  with_config :i18n_lookups_by_default, false do
706
779
  ::I18n.backend.store_translations :en,
707
- :formtastic => {
708
- :hints => {
709
- :post => {
710
- :title => @localized_hint_text
711
- }
712
- }
713
- }
780
+ :formtastic => {
781
+ :hints => {
782
+ :post => {
783
+ :title => @localized_hint_text
784
+ }
785
+ }
786
+ }
714
787
  concat(semantic_form_for(@new_post) do |builder|
715
788
  concat(builder.input(:title, :hint => true))
716
789
  end)
717
- output_buffer.should have_tag('form li p.inline-hints', @localized_hint_text)
718
- end
719
- end
720
-
721
- it 'should render a hint paragraph containing a localized hint (I18n) with a custom hint class if i ask for one' do
722
- with_config :i18n_lookups_by_default, false do
723
- ::I18n.backend.store_translations :en,
724
- :formtastic => {
725
- :hints => {
726
- :post => {
727
- :title => @localized_hint_text
728
- }
729
- }
730
- }
731
- concat(semantic_form_for(@new_post) do |builder|
732
- concat(builder.input(:title, :hint => true, :hint_class => 'custom-hint-class'))
733
- end)
734
- output_buffer.should have_tag('form li p.custom-hint-class', @localized_hint_text)
790
+ expect(output_buffer).to have_tag('form li p.inline-hints', :text => @localized_hint_text)
735
791
  end
736
792
  end
737
793
 
@@ -740,7 +796,7 @@ describe 'Formtastic::FormBuilder#input' do
740
796
  concat(semantic_form_for(@new_post) do |builder|
741
797
  concat(builder.input(:title, :hint => true))
742
798
  end)
743
- output_buffer.should have_tag('form li p.inline-hints', @default_localized_hint_text)
799
+ expect(output_buffer).to have_tag('form li p.inline-hints', :text => @default_localized_hint_text)
744
800
  end
745
801
  end
746
802
  end
@@ -751,7 +807,7 @@ describe 'Formtastic::FormBuilder#input' do
751
807
  concat(semantic_form_for(@new_post) do |builder|
752
808
  concat(builder.input(:title, :hint => false))
753
809
  end)
754
- output_buffer.should_not have_tag('form li p.inline-hints', @localized_hint_text)
810
+ expect(output_buffer).not_to have_tag('form li p.inline-hints', :text => @localized_hint_text)
755
811
  end
756
812
  end
757
813
  end
@@ -761,17 +817,17 @@ describe 'Formtastic::FormBuilder#input' do
761
817
  it "should see the provided hash as a blank entry" do
762
818
  with_config :i18n_lookups_by_default, false do
763
819
  ::I18n.backend.store_translations :en,
764
- :formtastic => {
765
- :hints => {
766
- :title => { # movie title
767
- :summary => @localized_hint_text # summary of movie
768
- }
769
- }
770
- }
820
+ :formtastic => {
821
+ :hints => {
822
+ :title => { # movie title
823
+ :summary => @localized_hint_text # summary of movie
824
+ }
825
+ }
826
+ }
771
827
  semantic_form_for(@new_post) do |builder|
772
828
  concat(builder.input(:title, :hint => true))
773
829
  end
774
- output_buffer.should_not have_tag('form li p.inline-hints', @localized_hint_text)
830
+ expect(output_buffer).not_to have_tag('form li p.inline-hints', :text => @localized_hint_text)
775
831
  end
776
832
  end
777
833
  end
@@ -782,7 +838,7 @@ describe 'Formtastic::FormBuilder#input' do
782
838
  concat(semantic_form_for(@new_post) do |builder|
783
839
  concat(builder.input(:title))
784
840
  end)
785
- output_buffer.should_not have_tag('form li p.inline-hints')
841
+ expect(output_buffer).not_to have_tag('form li p.inline-hints')
786
842
  end
787
843
  end
788
844
  end
@@ -797,25 +853,34 @@ describe 'Formtastic::FormBuilder#input' do
797
853
  concat(semantic_form_for(@new_post) do |builder|
798
854
  concat(builder.input(:title, :wrapper_html => {:id => :another_id}))
799
855
  end)
800
- output_buffer.should have_tag("form li#another_id")
856
+ expect(output_buffer).to have_tag("form li#another_id")
801
857
  end
802
858
 
803
859
  it 'should append given classes to li default classes' do
804
860
  concat(semantic_form_for(@new_post) do |builder|
805
861
  concat(builder.input(:title, :wrapper_html => {:class => :another_class}, :required => true))
806
862
  end)
807
- output_buffer.should have_tag("form li.string")
808
- output_buffer.should have_tag("form li.required")
809
- output_buffer.should have_tag("form li.another_class")
863
+ expect(output_buffer).to have_tag("form li.string")
864
+ expect(output_buffer).to have_tag("form li.required")
865
+ expect(output_buffer).to have_tag("form li.another_class")
810
866
  end
811
867
 
812
868
  it 'should allow classes to be an array' do
813
869
  concat(semantic_form_for(@new_post) do |builder|
814
870
  concat(builder.input(:title, :wrapper_html => {:class => [ :my_class, :another_class ]}))
815
871
  end)
816
- output_buffer.should have_tag("form li.string")
817
- output_buffer.should have_tag("form li.my_class")
818
- output_buffer.should have_tag("form li.another_class")
872
+ expect(output_buffer).to have_tag("form li.string")
873
+ expect(output_buffer).to have_tag("form li.my_class")
874
+ expect(output_buffer).to have_tag("form li.another_class")
875
+ end
876
+
877
+ describe 'when nil' do
878
+ it 'should not put an id attribute on the div tag' do
879
+ concat(semantic_form_for(@new_post) do |builder|
880
+ concat(builder.input(:title, :wrapper_html => {:id => nil}))
881
+ end)
882
+ expect(output_buffer).to have_tag('form li:not([id])')
883
+ end
819
884
  end
820
885
  end
821
886
 
@@ -824,8 +889,8 @@ describe 'Formtastic::FormBuilder#input' do
824
889
  concat(semantic_form_for(@new_post) do |builder|
825
890
  concat(builder.input(:title))
826
891
  end)
827
- output_buffer.should have_tag("form li#post_title_input")
828
- output_buffer.should have_tag("form li.string")
892
+ expect(output_buffer).to have_tag("form li#post_title_input")
893
+ expect(output_buffer).to have_tag("form li.string")
829
894
  end
830
895
  end
831
896
 
@@ -834,15 +899,15 @@ describe 'Formtastic::FormBuilder#input' do
834
899
  describe ':collection option' do
835
900
 
836
901
  it "should be required on polymorphic associations" do
837
- @new_post.stub!(:commentable)
838
- @new_post.class.stub!(:reflections).and_return({
839
- :commentable => mock('macro_reflection', :options => { :polymorphic => true }, :macro => :belongs_to)
840
- })
841
- @new_post.stub!(:column_for_attribute).with(:commentable).and_return(
842
- mock('column', :type => :integer)
902
+ allow(@new_post).to receive(:commentable)
903
+ allow(@new_post.class).to receive(:reflections).and_return({
904
+ :commentable => double('macro_reflection', :options => { :polymorphic => true }, :macro => :belongs_to)
905
+ })
906
+ allow(@new_post).to receive(:column_for_attribute).with(:commentable).and_return(
907
+ double('column', :type => :integer)
843
908
  )
844
- @new_post.class.stub!(:reflect_on_association).with(:commentable).and_return(
845
- mock('reflection', :macro => :belongs_to, :options => { :polymorphic => true })
909
+ allow(@new_post.class).to receive(:reflect_on_association).with(:commentable).and_return(
910
+ double('reflection', :macro => :belongs_to, :options => { :polymorphic => true })
846
911
  )
847
912
  expect {
848
913
  concat(semantic_form_for(@new_post) do |builder|
@@ -867,29 +932,26 @@ describe 'Formtastic::FormBuilder#input' do
867
932
  concat(builder.input(:title, my_options))
868
933
  concat(builder.input(:publish_at, my_options))
869
934
  end)
870
- output_buffer.should have_tag 'li.string', :count => 2
935
+ expect(output_buffer).to have_tag 'li.string', :count => 2
871
936
  end
872
-
873
-
874
937
  end
875
938
 
876
939
  describe 'instantiating an input class' do
877
-
878
940
  context 'when a class does not exist' do
879
941
  it "should raise an error" do
880
- lambda {
942
+ expect {
881
943
  concat(semantic_form_for(@new_post) do |builder|
882
944
  builder.input(:title, :as => :non_existant)
883
945
  end)
884
- }.should raise_error(Formtastic::UnknownInputError)
946
+ }.to raise_error(Formtastic::UnknownInputError)
885
947
  end
886
948
  end
887
949
 
888
950
  context 'when a customized top-level class does not exist' do
889
951
 
890
952
  it 'should instantiate the Formtastic input' do
891
- input = mock('input', :to_html => 'some HTML')
892
- Formtastic::Inputs::StringInput.should_receive(:new).and_return(input)
953
+ input = double('input', :to_html => 'some HTML')
954
+ expect(Formtastic::Inputs::StringInput).to receive(:new).and_return(input)
893
955
  concat(semantic_form_for(@new_post) do |builder|
894
956
  builder.input(:title, :as => :string)
895
957
  end)
@@ -902,9 +964,9 @@ describe 'Formtastic::FormBuilder#input' do
902
964
  class ::StringInput < Formtastic::Inputs::StringInput
903
965
  end
904
966
 
905
- input = mock('input', :to_html => 'some HTML')
906
- Formtastic::Inputs::StringInput.should_not_receive(:new).and_return(input)
907
- ::StringInput.should_receive(:new).and_return(input)
967
+ input = double('input', :to_html => 'some HTML')
968
+ expect(Formtastic::Inputs::StringInput).not_to receive(:new)
969
+ expect(::StringInput).to receive(:new).and_return(input)
908
970
 
909
971
  concat(semantic_form_for(@new_post) do |builder|
910
972
  builder.input(:title, :as => :string)
@@ -912,20 +974,6 @@ describe 'Formtastic::FormBuilder#input' do
912
974
  end
913
975
  end
914
976
 
915
- describe 'when instantiated multiple times with the same input type' do
916
-
917
- it "should be cached (not calling the internal methods)" do
918
- # TODO this is really tied to the underlying implementation
919
- concat(semantic_form_for(@new_post) do |builder|
920
- builder.should_receive(:custom_input_class_name).with(:string).once.and_return(::Formtastic::Inputs::StringInput)
921
- builder.input(:title, :as => :string)
922
- builder.input(:title, :as => :string)
923
- end)
924
- end
925
-
926
- end
927
977
 
928
978
  end
929
-
930
979
  end
931
-