mega-safe-tool 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. checksums.yaml +7 -0
  2. data/formtastic-6.0.0/Appraisals +23 -0
  3. data/formtastic-6.0.0/CONTRIBUTING.md +27 -0
  4. data/formtastic-6.0.0/Gemfile +8 -0
  5. data/formtastic-6.0.0/MIT-LICENSE +20 -0
  6. data/formtastic-6.0.0/README.md +600 -0
  7. data/formtastic-6.0.0/RELEASE_PROCESS +7 -0
  8. data/formtastic-6.0.0/Rakefile +54 -0
  9. data/formtastic-6.0.0/bin/appraisal +8 -0
  10. data/formtastic-6.0.0/formtastic.gemspec +45 -0
  11. data/formtastic-6.0.0/gemfiles/rails_72.gemfile +9 -0
  12. data/formtastic-6.0.0/gemfiles/rails_80.gemfile +9 -0
  13. data/formtastic-6.0.0/gemfiles/rails_81.gemfile +9 -0
  14. data/formtastic-6.0.0/gemfiles/rails_edge.gemfile +9 -0
  15. data/formtastic-6.0.0/lib/formtastic/action_class_finder.rb +19 -0
  16. data/formtastic-6.0.0/lib/formtastic/actions/base.rb +157 -0
  17. data/formtastic-6.0.0/lib/formtastic/actions/button_action.rb +68 -0
  18. data/formtastic-6.0.0/lib/formtastic/actions/buttonish.rb +18 -0
  19. data/formtastic-6.0.0/lib/formtastic/actions/input_action.rb +71 -0
  20. data/formtastic-6.0.0/lib/formtastic/actions/link_action.rb +89 -0
  21. data/formtastic-6.0.0/lib/formtastic/actions.rb +15 -0
  22. data/formtastic-6.0.0/lib/formtastic/deprecation.rb +6 -0
  23. data/formtastic-6.0.0/lib/formtastic/form_builder.rb +109 -0
  24. data/formtastic-6.0.0/lib/formtastic/helpers/action_helper.rb +115 -0
  25. data/formtastic-6.0.0/lib/formtastic/helpers/actions_helper.rb +169 -0
  26. data/formtastic-6.0.0/lib/formtastic/helpers/enum.rb +14 -0
  27. data/formtastic-6.0.0/lib/formtastic/helpers/errors_helper.rb +139 -0
  28. data/formtastic-6.0.0/lib/formtastic/helpers/fieldset_wrapper.rb +85 -0
  29. data/formtastic-6.0.0/lib/formtastic/helpers/file_column_detection.rb +17 -0
  30. data/formtastic-6.0.0/lib/formtastic/helpers/form_helper.rb +204 -0
  31. data/formtastic-6.0.0/lib/formtastic/helpers/input_helper.rb +349 -0
  32. data/formtastic-6.0.0/lib/formtastic/helpers/inputs_helper.rb +421 -0
  33. data/formtastic-6.0.0/lib/formtastic/helpers/reflection.rb +38 -0
  34. data/formtastic-6.0.0/lib/formtastic/helpers.rb +16 -0
  35. data/formtastic-6.0.0/lib/formtastic/html_attributes.rb +33 -0
  36. data/formtastic-6.0.0/lib/formtastic/i18n.rb +33 -0
  37. data/formtastic-6.0.0/lib/formtastic/input_class_finder.rb +19 -0
  38. data/formtastic-6.0.0/lib/formtastic/inputs/base/aria.rb +26 -0
  39. data/formtastic-6.0.0/lib/formtastic/inputs/base/associations.rb +32 -0
  40. data/formtastic-6.0.0/lib/formtastic/inputs/base/choices.rb +109 -0
  41. data/formtastic-6.0.0/lib/formtastic/inputs/base/collections.rb +158 -0
  42. data/formtastic-6.0.0/lib/formtastic/inputs/base/database.rb +20 -0
  43. data/formtastic-6.0.0/lib/formtastic/inputs/base/datetime_pickerish.rb +86 -0
  44. data/formtastic-6.0.0/lib/formtastic/inputs/base/errors.rb +59 -0
  45. data/formtastic-6.0.0/lib/formtastic/inputs/base/fileish.rb +24 -0
  46. data/formtastic-6.0.0/lib/formtastic/inputs/base/hints.rb +32 -0
  47. data/formtastic-6.0.0/lib/formtastic/inputs/base/html.rb +54 -0
  48. data/formtastic-6.0.0/lib/formtastic/inputs/base/labelling.rb +53 -0
  49. data/formtastic-6.0.0/lib/formtastic/inputs/base/naming.rb +43 -0
  50. data/formtastic-6.0.0/lib/formtastic/inputs/base/numeric.rb +51 -0
  51. data/formtastic-6.0.0/lib/formtastic/inputs/base/options.rb +18 -0
  52. data/formtastic-6.0.0/lib/formtastic/inputs/base/placeholder.rb +18 -0
  53. data/formtastic-6.0.0/lib/formtastic/inputs/base/stringish.rb +39 -0
  54. data/formtastic-6.0.0/lib/formtastic/inputs/base/timeish.rb +246 -0
  55. data/formtastic-6.0.0/lib/formtastic/inputs/base/validations.rb +250 -0
  56. data/formtastic-6.0.0/lib/formtastic/inputs/base/wrapping.rb +51 -0
  57. data/formtastic-6.0.0/lib/formtastic/inputs/base.rb +79 -0
  58. data/formtastic-6.0.0/lib/formtastic/inputs/boolean_input.rb +119 -0
  59. data/formtastic-6.0.0/lib/formtastic/inputs/check_boxes_input.rb +198 -0
  60. data/formtastic-6.0.0/lib/formtastic/inputs/color_input.rb +42 -0
  61. data/formtastic-6.0.0/lib/formtastic/inputs/country_input.rb +90 -0
  62. data/formtastic-6.0.0/lib/formtastic/inputs/datalist_input.rb +42 -0
  63. data/formtastic-6.0.0/lib/formtastic/inputs/date_picker_input.rb +94 -0
  64. data/formtastic-6.0.0/lib/formtastic/inputs/date_select_input.rb +35 -0
  65. data/formtastic-6.0.0/lib/formtastic/inputs/datetime_picker_input.rb +104 -0
  66. data/formtastic-6.0.0/lib/formtastic/inputs/datetime_select_input.rb +13 -0
  67. data/formtastic-6.0.0/lib/formtastic/inputs/email_input.rb +42 -0
  68. data/formtastic-6.0.0/lib/formtastic/inputs/file_input.rb +43 -0
  69. data/formtastic-6.0.0/lib/formtastic/inputs/hidden_input.rb +63 -0
  70. data/formtastic-6.0.0/lib/formtastic/inputs/number_input.rb +89 -0
  71. data/formtastic-6.0.0/lib/formtastic/inputs/password_input.rb +42 -0
  72. data/formtastic-6.0.0/lib/formtastic/inputs/phone_input.rb +43 -0
  73. data/formtastic-6.0.0/lib/formtastic/inputs/radio_input.rb +164 -0
  74. data/formtastic-6.0.0/lib/formtastic/inputs/range_input.rb +96 -0
  75. data/formtastic-6.0.0/lib/formtastic/inputs/search_input.rb +42 -0
  76. data/formtastic-6.0.0/lib/formtastic/inputs/select_input.rb +236 -0
  77. data/formtastic-6.0.0/lib/formtastic/inputs/string_input.rb +37 -0
  78. data/formtastic-6.0.0/lib/formtastic/inputs/text_input.rb +49 -0
  79. data/formtastic-6.0.0/lib/formtastic/inputs/time_picker_input.rb +100 -0
  80. data/formtastic-6.0.0/lib/formtastic/inputs/time_select_input.rb +39 -0
  81. data/formtastic-6.0.0/lib/formtastic/inputs/time_zone_input.rb +59 -0
  82. data/formtastic-6.0.0/lib/formtastic/inputs/url_input.rb +42 -0
  83. data/formtastic-6.0.0/lib/formtastic/inputs.rb +43 -0
  84. data/formtastic-6.0.0/lib/formtastic/localized_string.rb +18 -0
  85. data/formtastic-6.0.0/lib/formtastic/localizer.rb +151 -0
  86. data/formtastic-6.0.0/lib/formtastic/namespaced_class_finder.rb +98 -0
  87. data/formtastic-6.0.0/lib/formtastic/version.rb +4 -0
  88. data/formtastic-6.0.0/lib/formtastic.rb +48 -0
  89. data/formtastic-6.0.0/lib/generators/formtastic/form/form_generator.rb +111 -0
  90. data/formtastic-6.0.0/lib/generators/formtastic/input/input_generator.rb +47 -0
  91. data/formtastic-6.0.0/lib/generators/formtastic/install/install_generator.rb +23 -0
  92. data/formtastic-6.0.0/lib/generators/formtastic/stylesheets/stylesheets_generator.rb +15 -0
  93. data/formtastic-6.0.0/lib/generators/templates/_form.html.erb +11 -0
  94. data/formtastic-6.0.0/lib/generators/templates/_form.html.haml +8 -0
  95. data/formtastic-6.0.0/lib/generators/templates/_form.html.slim +8 -0
  96. data/formtastic-6.0.0/lib/generators/templates/formtastic.css +289 -0
  97. data/formtastic-6.0.0/lib/generators/templates/formtastic.rb +118 -0
  98. data/formtastic-6.0.0/lib/generators/templates/input.rb +19 -0
  99. data/formtastic-6.0.0/lib/locale/en.yml +10 -0
  100. data/formtastic-6.0.0/sample/basic_inputs.html +224 -0
  101. data/formtastic-6.0.0/sample/config.ru +69 -0
  102. data/formtastic-6.0.0/sample/index.html +14 -0
  103. data/formtastic-6.0.0/script/integration-template.rb +76 -0
  104. data/formtastic-6.0.0/script/integration.sh +32 -0
  105. data/formtastic-6.0.0/spec/action_class_finder_spec.rb +12 -0
  106. data/formtastic-6.0.0/spec/actions/button_action_spec.rb +63 -0
  107. data/formtastic-6.0.0/spec/actions/generic_action_spec.rb +521 -0
  108. data/formtastic-6.0.0/spec/actions/input_action_spec.rb +59 -0
  109. data/formtastic-6.0.0/spec/actions/link_action_spec.rb +92 -0
  110. data/formtastic-6.0.0/spec/builder/custom_builder_spec.rb +132 -0
  111. data/formtastic-6.0.0/spec/builder/error_proc_spec.rb +27 -0
  112. data/formtastic-6.0.0/spec/builder/semantic_fields_for_spec.rb +213 -0
  113. data/formtastic-6.0.0/spec/fast_spec_helper.rb +12 -0
  114. data/formtastic-6.0.0/spec/generators/formtastic/form/form_generator_spec.rb +132 -0
  115. data/formtastic-6.0.0/spec/generators/formtastic/input/input_generator_spec.rb +125 -0
  116. data/formtastic-6.0.0/spec/generators/formtastic/install/install_generator_spec.rb +48 -0
  117. data/formtastic-6.0.0/spec/generators/formtastic/stylesheets/stylesheets_generator_spec.rb +22 -0
  118. data/formtastic-6.0.0/spec/helpers/action_helper_spec.rb +338 -0
  119. data/formtastic-6.0.0/spec/helpers/actions_helper_spec.rb +143 -0
  120. data/formtastic-6.0.0/spec/helpers/form_helper_spec.rb +224 -0
  121. data/formtastic-6.0.0/spec/helpers/input_helper_spec.rb +991 -0
  122. data/formtastic-6.0.0/spec/helpers/inputs_helper_spec.rb +669 -0
  123. data/formtastic-6.0.0/spec/helpers/reflection_helper_spec.rb +32 -0
  124. data/formtastic-6.0.0/spec/helpers/semantic_errors_helper_spec.rb +220 -0
  125. data/formtastic-6.0.0/spec/i18n_spec.rb +210 -0
  126. data/formtastic-6.0.0/spec/input_class_finder_spec.rb +10 -0
  127. data/formtastic-6.0.0/spec/inputs/base/collections_spec.rb +119 -0
  128. data/formtastic-6.0.0/spec/inputs/base/validations_spec.rb +481 -0
  129. data/formtastic-6.0.0/spec/inputs/boolean_input_spec.rb +254 -0
  130. data/formtastic-6.0.0/spec/inputs/check_boxes_input_spec.rb +547 -0
  131. data/formtastic-6.0.0/spec/inputs/color_input_spec.rb +85 -0
  132. data/formtastic-6.0.0/spec/inputs/country_input_spec.rb +133 -0
  133. data/formtastic-6.0.0/spec/inputs/custom_input_spec.rb +51 -0
  134. data/formtastic-6.0.0/spec/inputs/datalist_input_spec.rb +61 -0
  135. data/formtastic-6.0.0/spec/inputs/date_picker_input_spec.rb +449 -0
  136. data/formtastic-6.0.0/spec/inputs/date_select_input_spec.rb +249 -0
  137. data/formtastic-6.0.0/spec/inputs/datetime_picker_input_spec.rb +490 -0
  138. data/formtastic-6.0.0/spec/inputs/datetime_select_input_spec.rb +209 -0
  139. data/formtastic-6.0.0/spec/inputs/email_input_spec.rb +85 -0
  140. data/formtastic-6.0.0/spec/inputs/file_input_spec.rb +89 -0
  141. data/formtastic-6.0.0/spec/inputs/hidden_input_spec.rb +135 -0
  142. data/formtastic-6.0.0/spec/inputs/include_blank_spec.rb +78 -0
  143. data/formtastic-6.0.0/spec/inputs/label_spec.rb +181 -0
  144. data/formtastic-6.0.0/spec/inputs/number_input_spec.rb +815 -0
  145. data/formtastic-6.0.0/spec/inputs/password_input_spec.rb +99 -0
  146. data/formtastic-6.0.0/spec/inputs/phone_input_spec.rb +85 -0
  147. data/formtastic-6.0.0/spec/inputs/placeholder_spec.rb +71 -0
  148. data/formtastic-6.0.0/spec/inputs/radio_input_spec.rb +326 -0
  149. data/formtastic-6.0.0/spec/inputs/range_input_spec.rb +505 -0
  150. data/formtastic-6.0.0/spec/inputs/readonly_spec.rb +50 -0
  151. data/formtastic-6.0.0/spec/inputs/search_input_spec.rb +84 -0
  152. data/formtastic-6.0.0/spec/inputs/select_input_spec.rb +661 -0
  153. data/formtastic-6.0.0/spec/inputs/string_input_spec.rb +326 -0
  154. data/formtastic-6.0.0/spec/inputs/text_input_spec.rb +187 -0
  155. data/formtastic-6.0.0/spec/inputs/time_picker_input_spec.rb +455 -0
  156. data/formtastic-6.0.0/spec/inputs/time_select_input_spec.rb +261 -0
  157. data/formtastic-6.0.0/spec/inputs/time_zone_input_spec.rb +143 -0
  158. data/formtastic-6.0.0/spec/inputs/url_input_spec.rb +85 -0
  159. data/formtastic-6.0.0/spec/inputs/with_options_spec.rb +43 -0
  160. data/formtastic-6.0.0/spec/localizer_spec.rb +130 -0
  161. data/formtastic-6.0.0/spec/namespaced_class_finder_spec.rb +90 -0
  162. data/formtastic-6.0.0/spec/schema.rb +22 -0
  163. data/formtastic-6.0.0/spec/spec.opts +2 -0
  164. data/formtastic-6.0.0/spec/spec_helper.rb +466 -0
  165. data/formtastic-6.0.0/spec/support/custom_macros.rb +570 -0
  166. data/formtastic-6.0.0/spec/support/deprecation.rb +7 -0
  167. data/formtastic-6.0.0/spec/support/shared_examples.rb +13 -0
  168. data/formtastic-6.0.0/spec/support/specialized_class_finder_shared_example.rb +27 -0
  169. data/formtastic-6.0.0/spec/support/test_environment.rb +46 -0
  170. data/mega-safe-tool.gemspec +11 -0
  171. metadata +209 -0
@@ -0,0 +1,991 @@
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+
4
+ RSpec.describe 'with input class finder' do
5
+ include_context 'form builder'
6
+
7
+ before do
8
+ @errors = double('errors')
9
+ allow(@errors).to receive(:[]).and_return([])
10
+ allow(@new_post).to receive(:errors).and_return(@errors)
11
+ end
12
+
13
+ describe 'arguments and options' do
14
+
15
+ it 'should require the first argument (the method on form\'s object)' do
16
+ expect {
17
+ concat(semantic_form_for(@new_post) do |builder|
18
+ concat(builder.input()) # no args passed in at all
19
+ end)
20
+ }.to raise_error(ArgumentError)
21
+ end
22
+
23
+ describe ':required option' do
24
+
25
+ describe 'when true' do
26
+
27
+ it 'should set a "required" class' do
28
+ with_config :required_string, " required yo!" do
29
+ concat(semantic_form_for(@new_post) do |builder|
30
+ concat(builder.input(:title, :required => true))
31
+ end)
32
+ expect(output_buffer.to_str).not_to have_tag('form li.optional')
33
+ expect(output_buffer.to_str).to have_tag('form li.required')
34
+ end
35
+ end
36
+
37
+ it 'should append the "required" string to the label' do
38
+ with_config :required_string, " required yo!" do
39
+ concat(semantic_form_for(@new_post) do |builder|
40
+ concat(builder.input(:title, :required => true))
41
+ end)
42
+ expect(output_buffer.to_str).to have_tag('form li.required label', :text => /required yo/)
43
+ end
44
+ end
45
+ end
46
+
47
+ describe 'when false' do
48
+
49
+ before do
50
+ @string = Formtastic::FormBuilder.optional_string = " optional yo!" # ensure there's something in the string
51
+ expect(@new_post.class).not_to receive(:reflect_on_all_validations)
52
+ end
53
+
54
+ after do
55
+ Formtastic::FormBuilder.optional_string = ''
56
+ end
57
+
58
+ it 'should set an "optional" class' do
59
+ concat(semantic_form_for(@new_post) do |builder|
60
+ concat(builder.input(:title, :required => false))
61
+ end)
62
+ expect(output_buffer.to_str).not_to have_tag('form li.required')
63
+ expect(output_buffer.to_str).to have_tag('form li.optional')
64
+ end
65
+
66
+ it 'should set and "optional" class also when there is presence validator' do
67
+ expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
68
+ active_model_presence_validator([:title])
69
+ ])
70
+ concat(semantic_form_for(@new_post) do |builder|
71
+ concat(builder.input(:title, :required => false))
72
+ end)
73
+ expect(output_buffer.to_str).not_to have_tag('form li.required')
74
+ expect(output_buffer.to_str).to have_tag('form li.optional')
75
+ end
76
+
77
+ it 'should append the "optional" string to the label' do
78
+ concat(semantic_form_for(@new_post) do |builder|
79
+ concat(builder.input(:title, :required => false))
80
+ end)
81
+ expect(output_buffer.to_str).to have_tag('form li.optional label', :text => /#{@string}$/)
82
+ end
83
+
84
+ end
85
+
86
+ describe 'when not provided' do
87
+
88
+ describe 'and an object was not given' do
89
+
90
+ it 'should use the default value' do
91
+ expect(Formtastic::FormBuilder.all_fields_required_by_default).to eq(true)
92
+ Formtastic::FormBuilder.all_fields_required_by_default = false
93
+
94
+ concat(semantic_form_for(:project, :url => 'http://test.host/') do |builder|
95
+ concat(builder.input(:title))
96
+ end)
97
+ expect(output_buffer.to_str).not_to have_tag('form li.required')
98
+ expect(output_buffer.to_str).to have_tag('form li.optional')
99
+
100
+ Formtastic::FormBuilder.all_fields_required_by_default = true
101
+ end
102
+
103
+ end
104
+
105
+ describe 'and an object with :validators_on was given (ActiveModel, Active Resource)' do
106
+ before do
107
+ allow(@new_post).to receive(:class).and_return(::PostModel)
108
+ end
109
+
110
+ after do
111
+ allow(@new_post).to receive(:class).and_return(::Post)
112
+ end
113
+ describe 'and validates_presence_of was called for the method' do
114
+ it 'should be required' do
115
+
116
+ expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
117
+ active_model_presence_validator([:title])
118
+ ])
119
+
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
+ ])
123
+
124
+ concat(semantic_form_for(@new_post) do |builder|
125
+ concat(builder.input(:title))
126
+ concat(builder.input(:body))
127
+ end)
128
+ expect(output_buffer.to_str).to have_tag('form li.required')
129
+ expect(output_buffer.to_str).not_to have_tag('form li.optional')
130
+ end
131
+
132
+ it 'should be required when there is :on => :create option on create' do
133
+ with_config :required_string, " required yo!" do
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_str).to have_tag('form li.required')
141
+ expect(output_buffer.to_str).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
+ ])
150
+ concat(semantic_form_for(@new_post) do |builder|
151
+ concat(builder.input(:title))
152
+ end)
153
+ expect(output_buffer.to_str).to have_tag('form li.required')
154
+ expect(output_buffer.to_str).not_to have_tag('form li.optional')
155
+ end
156
+ end
157
+
158
+ it 'should be required when there is :on => :save option on create' do
159
+ with_config :required_string, " required yo!" do
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
+ ])
163
+ concat(semantic_form_for(@new_post) do |builder|
164
+ concat(builder.input(:title))
165
+ end)
166
+ expect(output_buffer.to_str).to have_tag('form li.required')
167
+ expect(output_buffer.to_str).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_str).to have_tag('form li.required')
180
+ expect(output_buffer.to_str).not_to have_tag('form li.optional')
181
+ end
182
+ end
183
+
184
+ it 'should be required when there is :on => :save option on update' do
185
+ with_config :required_string, " required yo!" do
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_str).to have_tag('form li.required')
193
+ expect(output_buffer.to_str).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
+ ])
202
+ concat(semantic_form_for(@fred) do |builder|
203
+ concat(builder.input(:login))
204
+ end)
205
+ expect(output_buffer.to_str).to have_tag('form li.required')
206
+ expect(output_buffer.to_str).not_to have_tag('form li.optional')
207
+ end
208
+ end
209
+
210
+ it 'should not be required when there is :on => :create option on update' do
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.to_str).not_to have_tag('form li.required')
218
+ expect(output_buffer.to_str).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
+ ])
225
+ concat(semantic_form_for(@fred) do |builder|
226
+ concat(builder.input(:login))
227
+ end)
228
+ expect(output_buffer.to_str).not_to have_tag('form li.required')
229
+ expect(output_buffer.to_str).to have_tag('form li.optional')
230
+ end
231
+
232
+ it 'should not be required when there is :on => :update option on create' do
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.to_str).not_to have_tag('form li.required')
240
+ expect(output_buffer.to_str).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
+ ])
247
+ concat(semantic_form_for(@new_post) do |builder|
248
+ concat(builder.input(:title))
249
+ end)
250
+ expect(output_buffer.to_str).not_to have_tag('form li.required')
251
+ expect(output_buffer.to_str).to have_tag('form li.optional')
252
+ end
253
+
254
+ it 'should be not be required if the optional :if condition is not satisifed' do
255
+ presence_should_be_required(:required => false, :tag => :body, :options => { :if => false })
256
+ end
257
+
258
+ it 'should not be required if the optional :if proc evaluates to false' do
259
+ presence_should_be_required(:required => false, :tag => :body, :options => { :if => proc { |record| false } })
260
+ end
261
+
262
+ it 'should be required if the optional :if proc evaluates to true' do
263
+ presence_should_be_required(:required => true, :tag => :body, :options => { :if => proc { |record| true } })
264
+ end
265
+
266
+ it 'should not be required if the optional :unless proc evaluates to true' do
267
+ presence_should_be_required(:required => false, :tag => :body, :options => { :unless => proc { |record| true } })
268
+ end
269
+
270
+ it 'should be required if the optional :unless proc evaluates to false' do
271
+ presence_should_be_required(:required => true, :tag => :body, :options => { :unless => proc { |record| false } })
272
+ end
273
+
274
+ it 'should be required if the optional :if with a method string evaluates to true' do
275
+ expect(@new_post).to receive(:required_condition).and_return(true)
276
+ presence_should_be_required(:required => true, :tag => :body, :options => { :if => :required_condition })
277
+ end
278
+
279
+ it 'should be required if the optional :if with a method string evaluates to false' do
280
+ expect(@new_post).to receive(:required_condition).and_return(false)
281
+ presence_should_be_required(:required => false, :tag => :body, :options => { :if => :required_condition })
282
+ end
283
+
284
+ it 'should be required if the optional :unless with a method string evaluates to false' do
285
+ expect(@new_post).to receive(:required_condition).and_return(false)
286
+ presence_should_be_required(:required => true, :tag => :body, :options => { :unless => :required_condition })
287
+ end
288
+
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
293
+ end
294
+
295
+ describe 'and validates_inclusion_of was called for the method' do
296
+ it 'should be required' do
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
+ ])
300
+ should_be_required(:tag => :published, :required => true)
301
+ end
302
+
303
+ it 'should not be required if allow_blank is true' do
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
+ ])
307
+ should_be_required(:tag => :published, :required => false)
308
+ end
309
+ end
310
+
311
+ describe 'and validates_length_of was called for the method' do
312
+ it 'should be required if minimum is set' do
313
+ length_should_be_required(:tag => :title, :required => true, :options => {:minimum => 1})
314
+ end
315
+
316
+ it 'should be required if :within is set' do
317
+ length_should_be_required(:tag => :title, :required => true, :options => {:within => 1..5})
318
+ end
319
+
320
+ it 'should not be required if :within allows zero length' do
321
+ length_should_be_required(:tag => :title, :required => false, :options => {:within => 0..5})
322
+ end
323
+
324
+ it 'should not be required if only :minimum is zero' do
325
+ length_should_be_required(:tag => :title, :required => false, :options => {:minimum => 0})
326
+ end
327
+
328
+ it 'should not be required if only :minimum is not set' do
329
+ length_should_be_required(:tag => :title, :required => false, :options => {:maximum => 5})
330
+ end
331
+
332
+ it 'should not be required if allow_blank is true' do
333
+ length_should_be_required(:tag => :published, :required => false, :options => {:allow_blank => true})
334
+ end
335
+ end
336
+
337
+ def add_presence_validator(options)
338
+ allow(@new_post.class).to receive(:validators_on).with(options[:tag]).and_return([
339
+ active_model_presence_validator([options[:tag]], options[:options])
340
+ ])
341
+ end
342
+
343
+ def add_length_validator(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])
346
+ ]}
347
+ end
348
+
349
+ # TODO make a matcher for this?
350
+ def should_be_required(options)
351
+ concat(semantic_form_for(@new_post) do |builder|
352
+ concat(builder.input(options[:tag]))
353
+ end)
354
+
355
+ if options[:required]
356
+ expect(output_buffer.to_str).not_to have_tag('form li.optional')
357
+ expect(output_buffer.to_str).to have_tag('form li.required')
358
+ else
359
+ expect(output_buffer.to_str).to have_tag('form li.optional')
360
+ expect(output_buffer.to_str).not_to have_tag('form li.required')
361
+ end
362
+ end
363
+
364
+ def presence_should_be_required(options)
365
+ add_presence_validator(options)
366
+ should_be_required(options)
367
+ end
368
+
369
+ def length_should_be_required(options)
370
+ add_length_validator(options)
371
+ should_be_required(options)
372
+ end
373
+
374
+ # TODO JF reversed this during refactor, need to make sure
375
+ describe 'and there are no requirement validations on the method' do
376
+ before do
377
+ expect(@new_post.class).to receive(:validators_on).with(:title).and_return([])
378
+ end
379
+
380
+ it 'should not be required' do
381
+ concat(semantic_form_for(@new_post) do |builder|
382
+ concat(builder.input(:title))
383
+ end)
384
+ expect(output_buffer.to_str).not_to have_tag('form li.required')
385
+ expect(output_buffer.to_str).to have_tag('form li.optional')
386
+ end
387
+ end
388
+
389
+ end
390
+
391
+ describe 'and an object without :validators_on' do
392
+
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
396
+
397
+ concat(semantic_form_for(@new_post) do |builder|
398
+ concat(builder.input(:title))
399
+ end)
400
+ expect(output_buffer.to_str).not_to have_tag('form li.required')
401
+ expect(output_buffer.to_str).to have_tag('form li.optional')
402
+
403
+ Formtastic::FormBuilder.all_fields_required_by_default = true
404
+ end
405
+
406
+ end
407
+
408
+ end
409
+
410
+ end
411
+
412
+ describe ':as option' do
413
+
414
+ describe 'when not provided' do
415
+
416
+ it 'should default to a string for forms without objects unless column is password' do
417
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
418
+ concat(builder.input(:anything))
419
+ end)
420
+ expect(output_buffer.to_str).to have_tag('form li.string')
421
+ end
422
+
423
+ it 'should default to password for forms without objects if column is password' do
424
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
425
+ concat(builder.input(:password))
426
+ concat(builder.input(:password_confirmation))
427
+ concat(builder.input(:confirm_password))
428
+ end)
429
+ expect(output_buffer.to_str).to have_tag('form li.password', :count => 3)
430
+ end
431
+
432
+ it 'should default to a string for methods on objects that don\'t respond to "column_for_attribute"' do
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)
436
+ end
437
+
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
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)
442
+ end
443
+
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
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)
448
+ end
449
+
450
+ it 'should default to :number for "integer" column with name ending in "_id"' do
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)
454
+ end
455
+
456
+ it 'should default to :select for associations' do
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)
469
+ end
470
+
471
+ it 'should default to :password for :string column types with "password" in the method name' do
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)
475
+ end
476
+
477
+ it 'should default to :text for :text column types' do
478
+ expect(default_input_type(:text)).to eq(:text)
479
+ end
480
+
481
+ it 'should default to :date_select for :date column types' do
482
+ expect(default_input_type(:date)).to eq(:date_select)
483
+ end
484
+
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)
489
+ end
490
+
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
+ expect(default_input_type(:timestamptz)).to eq(:datetime_select)
495
+ end
496
+
497
+ it 'should default to :time_select for :time column types' do
498
+ expect(default_input_type(:time)).to eq(:time_select)
499
+ end
500
+
501
+ it 'should default to :boolean for :boolean column types' do
502
+ expect(default_input_type(:boolean)).to eq(:boolean)
503
+ end
504
+
505
+ it 'should default to :string for :string column types' do
506
+ expect(default_input_type(:string)).to eq(:string)
507
+ end
508
+
509
+ it 'should default to :string for :citext column types' do
510
+ expect(default_input_type(:citext)).to eq(:string)
511
+ end
512
+
513
+ it 'should default to :string for :inet column types' do
514
+ expect(default_input_type(:inet)).to eq(:string)
515
+ end
516
+
517
+ it 'should default to :number for :integer, :float and :decimal column types' do
518
+ expect(default_input_type(:integer)).to eq(:number)
519
+ expect(default_input_type(:float)).to eq(:number)
520
+ expect(default_input_type(:decimal)).to eq(:number)
521
+ end
522
+
523
+ it 'should default to :country for :string columns named country' do
524
+ expect(default_input_type(:string, :country)).to eq(:country)
525
+ end
526
+
527
+ it 'should default to :email for :string columns matching email' do
528
+ expect(default_input_type(:string, :email)).to eq(:email)
529
+ expect(default_input_type(:string, :customer_email)).to eq(:email)
530
+ expect(default_input_type(:string, :email_work)).to eq(:email)
531
+ end
532
+
533
+ it 'should default to :url for :string columns named url or website' do
534
+ expect(default_input_type(:string, :url)).to eq(:url)
535
+ expect(default_input_type(:string, :website)).to eq(:url)
536
+ expect(default_input_type(:string, :my_url)).to eq(:url)
537
+ expect(default_input_type(:string, :hurl)).not_to eq(:url)
538
+ end
539
+
540
+ it 'should default to :phone for :string columns named phone or fax' do
541
+ expect(default_input_type(:string, :phone)).to eq(:phone)
542
+ expect(default_input_type(:string, :fax)).to eq(:phone)
543
+ end
544
+
545
+ it 'should default to :search for :string columns named search' do
546
+ expect(default_input_type(:string, :search)).to eq(:search)
547
+ end
548
+
549
+ it 'should default to :color for :string columns matching color' do
550
+ expect(default_input_type(:string, :color)).to eq(:color)
551
+ expect(default_input_type(:string, :user_color)).to eq(:color)
552
+ expect(default_input_type(:string, :color_for_image)).to eq(:color)
553
+ end
554
+
555
+ describe 'defaulting to file column' do
556
+ Formtastic::FormBuilder.file_methods.each do |method|
557
+ it "should default to :file for attributes that respond to ##{method}" do
558
+ column = double('column')
559
+
560
+ Formtastic::FormBuilder.file_methods.each do |test|
561
+ ### TODO: Check if this is ok
562
+ allow(column).to receive(method).with(test).and_return(method == test)
563
+ end
564
+
565
+ expect(@new_post).to receive(method).and_return(column)
566
+
567
+ semantic_form_for(@new_post) do |builder|
568
+ expect(builder.send(:default_input_type, method)).to eq(:file)
569
+ end
570
+ end
571
+ end
572
+
573
+ end
574
+ end
575
+
576
+ it 'should call the corresponding input class with .to_html' do
577
+ [:select, :time_zone, :radio, :date_select, :datetime_select, :time_select, :boolean, :check_boxes, :hidden, :string, :password, :number, :text, :file].each do |input_style|
578
+ allow(@new_post).to receive(:generic_column_name)
579
+ allow(@new_post).to receive(:column_for_attribute).and_return(double('column', :type => :string, :limit => 255))
580
+ semantic_form_for(@new_post) do |builder|
581
+ input_instance = double('Input instance')
582
+ input_class = "#{input_style.to_s}_input".classify
583
+ input_constant = "Formtastic::Inputs::#{input_class}".constantize
584
+
585
+ expect(input_constant).to receive(:new).and_return(input_instance)
586
+ expect(input_instance).to receive(:to_html).and_return("some HTML")
587
+
588
+ concat(builder.input(:generic_column_name, :as => input_style))
589
+ end
590
+ end
591
+ end
592
+
593
+ end
594
+
595
+ describe ':label option' do
596
+
597
+ describe 'when provided' do
598
+ it 'should be passed down to the label tag' do
599
+ concat(semantic_form_for(@new_post) do |builder|
600
+ concat(builder.input(:title, :label => "Kustom"))
601
+ end)
602
+ expect(output_buffer.to_str).to have_tag("form li label", :text => /Kustom/)
603
+ end
604
+
605
+ it 'should not generate a label if false' do
606
+ concat(semantic_form_for(@new_post) do |builder|
607
+ concat(builder.input(:title, :label => false))
608
+ end)
609
+ expect(output_buffer.to_str).not_to have_tag("form li label")
610
+ end
611
+
612
+ it 'should be dupped if frozen' do
613
+ concat(semantic_form_for(@new_post) do |builder|
614
+ concat(builder.input(:title, :label => "Kustom".freeze))
615
+ end)
616
+ expect(output_buffer.to_str).to have_tag("form li label", :text => /Kustom/)
617
+ end
618
+ end
619
+
620
+ describe 'when not provided' do
621
+ describe 'when localized label is provided' do
622
+ describe 'and object is given' do
623
+ describe 'and label_str_method not :humanize' do
624
+ it 'should render a label with localized text and not apply the label_str_method' do
625
+ with_config :label_str_method, :reverse do
626
+ @localized_label_text = 'Localized title'
627
+ allow(@new_post).to receive(:meta_description)
628
+ ::I18n.backend.store_translations :en,
629
+ :formtastic => {
630
+ :labels => {
631
+ :meta_description => @localized_label_text
632
+ }
633
+ }
634
+
635
+ concat(semantic_form_for(@new_post) do |builder|
636
+ concat(builder.input(:meta_description))
637
+ end)
638
+ expect(output_buffer.to_str).to have_tag('form li label', :text => /Localized title/)
639
+ end
640
+ end
641
+ end
642
+ end
643
+ end
644
+
645
+ describe 'when localized label is NOT provided' do
646
+ describe 'and object is not given' do
647
+ it 'should default the humanized method name, passing it down to the label tag' do
648
+ ::I18n.backend.store_translations :en, :formtastic => {}
649
+ with_config :label_str_method, :humanize do
650
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
651
+ concat(builder.input(:meta_description))
652
+ end)
653
+ expect(output_buffer.to_str).to have_tag("form li label", :text => /#{'meta_description'.humanize}/)
654
+ end
655
+ end
656
+ end
657
+
658
+ describe 'and object is given' do
659
+ it 'should delegate the label logic to class human attribute name and pass it down to the label tag' do
660
+ allow(@new_post).to receive(:meta_description) # a two word method name
661
+ expect(@new_post.class).to receive(:human_attribute_name).with('meta_description').and_return('meta_description'.humanize)
662
+
663
+ concat(semantic_form_for(@new_post) do |builder|
664
+ concat(builder.input(:meta_description))
665
+ end)
666
+ expect(output_buffer.to_str).to have_tag("form li label", :text => /#{'meta_description'.humanize}/)
667
+ end
668
+ end
669
+
670
+ describe 'and object is given with label_str_method set to :capitalize' do
671
+ it 'should capitalize method name, passing it down to the label tag' do
672
+ with_config :label_str_method, :capitalize do
673
+ allow(@new_post).to receive(:meta_description)
674
+
675
+ concat(semantic_form_for(@new_post) do |builder|
676
+ concat(builder.input(:meta_description))
677
+ end)
678
+ expect(output_buffer.to_str).to have_tag("form li label", :text => /#{'meta_description'.capitalize}/)
679
+ end
680
+ end
681
+ end
682
+ end
683
+
684
+ describe 'when localized label is provided' do
685
+ before do
686
+ @localized_label_text = 'Localized title'
687
+ @default_localized_label_text = 'Default localized title'
688
+ ::I18n.backend.store_translations :en,
689
+ :formtastic => {
690
+ :labels => {
691
+ :title => @default_localized_label_text,
692
+ :published => @default_localized_label_text,
693
+ :post => {
694
+ :title => @localized_label_text,
695
+ :published => @default_localized_label_text
696
+ }
697
+ }
698
+ }
699
+ end
700
+
701
+ it 'should render a label with localized label (I18n)' do
702
+ with_config :i18n_lookups_by_default, false do
703
+ concat(semantic_form_for(@new_post) do |builder|
704
+ concat(builder.input(:title, :label => true))
705
+ concat(builder.input(:published, :as => :boolean, :label => true))
706
+ end)
707
+ expect(output_buffer.to_str).to have_tag('form li label', :text => Regexp.new('^' + @localized_label_text))
708
+ end
709
+ end
710
+
711
+ it 'should render a hint paragraph containing an optional localized label (I18n) if first is not set' do
712
+ with_config :i18n_lookups_by_default, false do
713
+ ::I18n.backend.store_translations :en,
714
+ :formtastic => {
715
+ :labels => {
716
+ :post => {
717
+ :title => nil,
718
+ :published => nil
719
+ }
720
+ }
721
+ }
722
+ concat(semantic_form_for(@new_post) do |builder|
723
+ concat(builder.input(:title, :label => true))
724
+ concat(builder.input(:published, :as => :boolean, :label => true))
725
+ end)
726
+ expect(output_buffer.to_str).to have_tag('form li label', :text => Regexp.new('^' + @default_localized_label_text))
727
+ end
728
+ end
729
+ end
730
+ end
731
+
732
+ end
733
+
734
+ describe ':label_method option' do
735
+ it "should allow label_html to add custom attributes" do
736
+ concat(semantic_form_for(@new_post) do |builder|
737
+ concat(builder.input(:title, :label_html => { :data => { :tooltip => 'Great Tooltip' } }))
738
+ end)
739
+ aggregate_failures do
740
+ expect(output_buffer.to_str).to have_tag('form li label[data-tooltip="Great Tooltip"]')
741
+ end
742
+ end
743
+ end
744
+
745
+ describe ':hint option' do
746
+
747
+ describe 'when provided' do
748
+
749
+ after do
750
+ Formtastic::FormBuilder.default_hint_class = "inline-hints"
751
+ end
752
+
753
+ it 'should be passed down to the paragraph tag' do
754
+ hint_text = "this is the title of the post"
755
+ concat(semantic_form_for(@new_post) do |builder|
756
+ concat(builder.input(:title, :hint => hint_text))
757
+ end)
758
+ expect(output_buffer.to_str).to have_tag("form li p.inline-hints", :text => hint_text)
759
+ end
760
+
761
+ it 'should have a custom hint class defaulted for all forms' do
762
+ hint_text = "this is the title of the post"
763
+ Formtastic::FormBuilder.default_hint_class = "custom-hint-class"
764
+ concat(semantic_form_for(@new_post) do |builder|
765
+ concat(builder.input(:title, :hint => hint_text))
766
+ end)
767
+ expect(output_buffer.to_str).to have_tag("form li p.custom-hint-class", :text => hint_text)
768
+ end
769
+ end
770
+
771
+ describe 'when not provided' do
772
+ describe 'when localized hint (I18n) is provided' do
773
+ before do
774
+ @localized_hint_text = "This is the localized hint."
775
+ @default_localized_hint_text = "This is the default localized hint."
776
+ ::I18n.backend.store_translations :en,
777
+ :formtastic => {
778
+ :hints => {
779
+ :title => @default_localized_hint_text,
780
+ }
781
+ }
782
+ end
783
+
784
+ after do
785
+ ::I18n.backend.reload!
786
+ end
787
+
788
+ describe 'when provided value (hint value) is set to TRUE' do
789
+ it 'should render a hint paragraph containing a localized hint (I18n)' do
790
+ with_config :i18n_lookups_by_default, false do
791
+ ::I18n.backend.store_translations :en,
792
+ :formtastic => {
793
+ :hints => {
794
+ :post => {
795
+ :title => @localized_hint_text
796
+ }
797
+ }
798
+ }
799
+ concat(semantic_form_for(@new_post) do |builder|
800
+ concat(builder.input(:title, :hint => true))
801
+ end)
802
+ expect(output_buffer.to_str).to have_tag('form li p.inline-hints', :text => @localized_hint_text)
803
+ end
804
+ end
805
+
806
+ it 'should render a hint paragraph containing an optional localized hint (I18n) if first is not set' do
807
+ with_config :i18n_lookups_by_default, false do
808
+ concat(semantic_form_for(@new_post) do |builder|
809
+ concat(builder.input(:title, :hint => true))
810
+ end)
811
+ expect(output_buffer.to_str).to have_tag('form li p.inline-hints', :text => @default_localized_hint_text)
812
+ end
813
+ end
814
+ end
815
+
816
+ describe 'when provided value (label value) is set to FALSE' do
817
+ it 'should not render a hint paragraph' do
818
+ with_config :i18n_lookups_by_default, false do
819
+ concat(semantic_form_for(@new_post) do |builder|
820
+ concat(builder.input(:title, :hint => false))
821
+ end)
822
+ expect(output_buffer.to_str).not_to have_tag('form li p.inline-hints', :text => @localized_hint_text)
823
+ end
824
+ end
825
+ end
826
+ end
827
+
828
+ describe 'when localized hint (I18n) is a model with attribute hints' do
829
+ it "should see the provided hash as a blank entry" do
830
+ with_config :i18n_lookups_by_default, false do
831
+ ::I18n.backend.store_translations :en,
832
+ :formtastic => {
833
+ :hints => {
834
+ :title => { # movie title
835
+ :summary => @localized_hint_text # summary of movie
836
+ }
837
+ }
838
+ }
839
+ semantic_form_for(@new_post) do |builder|
840
+ concat(builder.input(:title, :hint => true))
841
+ end
842
+ expect(output_buffer.to_str).not_to have_tag('form li p.inline-hints', :text => @localized_hint_text)
843
+ end
844
+ end
845
+ end
846
+
847
+ describe 'when localized hint (I18n) is not provided' do
848
+ it 'should not render a hint paragraph' do
849
+ with_config :i18n_lookups_by_default, false do
850
+ concat(semantic_form_for(@new_post) do |builder|
851
+ concat(builder.input(:title))
852
+ end)
853
+ expect(output_buffer.to_str).not_to have_tag('form li p.inline-hints')
854
+ end
855
+ end
856
+ end
857
+ end
858
+
859
+ end
860
+
861
+ describe ':wrapper_html option' do
862
+
863
+ describe 'when provided' do
864
+ it 'should be passed down to the li tag' do
865
+ concat(semantic_form_for(@new_post) do |builder|
866
+ concat(builder.input(:title, :wrapper_html => {:id => :another_id}))
867
+ end)
868
+ expect(output_buffer.to_str).to have_tag("form li#another_id")
869
+ end
870
+
871
+ it 'should append given classes to li default classes' do
872
+ concat(semantic_form_for(@new_post) do |builder|
873
+ concat(builder.input(:title, :wrapper_html => {:class => :another_class}, :required => true))
874
+ end)
875
+ expect(output_buffer.to_str).to have_tag("form li.string")
876
+ expect(output_buffer.to_str).to have_tag("form li.required")
877
+ expect(output_buffer.to_str).to have_tag("form li.another_class")
878
+ end
879
+
880
+ it 'should allow classes to be an array' do
881
+ concat(semantic_form_for(@new_post) do |builder|
882
+ concat(builder.input(:title, :wrapper_html => {:class => [ :my_class, :another_class ]}))
883
+ end)
884
+ expect(output_buffer.to_str).to have_tag("form li.string")
885
+ expect(output_buffer.to_str).to have_tag("form li.my_class")
886
+ expect(output_buffer.to_str).to have_tag("form li.another_class")
887
+ end
888
+
889
+ describe 'when nil' do
890
+ it 'should not put an id attribute on the div tag' do
891
+ concat(semantic_form_for(@new_post) do |builder|
892
+ concat(builder.input(:title, :wrapper_html => {:id => nil}))
893
+ end)
894
+ expect(output_buffer.to_str).to have_tag('form li:not([id])')
895
+ end
896
+ end
897
+ end
898
+
899
+ describe 'when not provided' do
900
+ it 'should use default id and class' do
901
+ concat(semantic_form_for(@new_post) do |builder|
902
+ concat(builder.input(:title))
903
+ end)
904
+ expect(output_buffer.to_str).to have_tag("form li#post_title_input")
905
+ expect(output_buffer.to_str).to have_tag("form li.string")
906
+ end
907
+ end
908
+
909
+ end
910
+
911
+ describe ':collection option' do
912
+
913
+ it "should be required on polymorphic associations" do
914
+ allow(@new_post).to receive(:commentable)
915
+ allow(@new_post.class).to receive(:reflections).and_return({
916
+ :commentable => double('macro_reflection', :options => { :polymorphic => true }, :macro => :belongs_to)
917
+ })
918
+ allow(@new_post).to receive(:column_for_attribute).with(:commentable).and_return(
919
+ double('column', :type => :integer)
920
+ )
921
+ allow(@new_post.class).to receive(:reflect_on_association).with(:commentable).and_return(
922
+ double('reflection', :macro => :belongs_to, :options => { :polymorphic => true })
923
+ )
924
+ expect {
925
+ concat(semantic_form_for(@new_post) do |builder|
926
+ concat(builder.inputs do
927
+ concat(builder.input :commentable)
928
+ end)
929
+ end)
930
+ }.to raise_error(Formtastic::PolymorphicInputWithoutCollectionError)
931
+ end
932
+
933
+ end
934
+
935
+ end
936
+
937
+ describe 'options re-use' do
938
+
939
+ it 'should retain :as option when re-using the same options hash' do
940
+ my_options = { :as => :string }
941
+ output = ''
942
+
943
+ concat(semantic_form_for(@new_post) do |builder|
944
+ concat(builder.input(:title, my_options))
945
+ concat(builder.input(:publish_at, my_options))
946
+ end)
947
+ expect(output_buffer.to_str).to have_tag 'li.string', :count => 2
948
+ end
949
+ end
950
+
951
+ describe 'instantiating an input class' do
952
+ context 'when a class does not exist' do
953
+ it "should raise an error" do
954
+ expect {
955
+ concat(semantic_form_for(@new_post) do |builder|
956
+ builder.input(:title, :as => :non_existant)
957
+ end)
958
+ }.to raise_error(Formtastic::UnknownInputError)
959
+ end
960
+ end
961
+
962
+ context 'when a customized top-level class does not exist' do
963
+
964
+ it 'should instantiate the Formtastic input' do
965
+ input = double('input', :to_html => 'some HTML')
966
+ expect(Formtastic::Inputs::StringInput).to receive(:new).and_return(input)
967
+ concat(semantic_form_for(@new_post) do |builder|
968
+ builder.input(:title, :as => :string)
969
+ end)
970
+ end
971
+
972
+ end
973
+
974
+ describe 'when a top-level input class exists' do
975
+ it "should instantiate the top-level input instead of the Formtastic one" do
976
+ class ::StringInput < Formtastic::Inputs::StringInput
977
+ end
978
+
979
+ input = double('input', :to_html => 'some HTML')
980
+ expect(Formtastic::Inputs::StringInput).not_to receive(:new)
981
+ expect(::StringInput).to receive(:new).and_return(input)
982
+
983
+ concat(semantic_form_for(@new_post) do |builder|
984
+ builder.input(:title, :as => :string)
985
+ end)
986
+ end
987
+ end
988
+
989
+
990
+ end
991
+ end