formtastic 1.2.4 → 3.1.5

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 (189) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +46 -0
  5. data/.yardopts +1 -0
  6. data/Appraisals +43 -0
  7. data/CHANGELOG +54 -0
  8. data/DEPRECATIONS +52 -0
  9. data/Gemfile +3 -0
  10. data/README.md +629 -0
  11. data/RELEASE_PROCESS +6 -0
  12. data/Rakefile +35 -0
  13. data/app/assets/stylesheets/formtastic.css +289 -0
  14. data/app/assets/stylesheets/formtastic_ie6.css +33 -0
  15. data/app/assets/stylesheets/formtastic_ie7.css +23 -0
  16. data/formtastic.gemspec +42 -0
  17. data/gemfiles/rails_3.2.gemfile +9 -0
  18. data/gemfiles/rails_4.0.4.gemfile +8 -0
  19. data/gemfiles/rails_4.1.gemfile +8 -0
  20. data/gemfiles/rails_4.2.gemfile +8 -0
  21. data/gemfiles/rails_4.gemfile +8 -0
  22. data/gemfiles/rails_5.0.gemfile +8 -0
  23. data/gemfiles/rails_edge.gemfile +15 -0
  24. data/lib/formtastic.rb +40 -1945
  25. data/lib/formtastic/action_class_finder.rb +18 -0
  26. data/lib/formtastic/actions.rb +11 -0
  27. data/lib/formtastic/actions/base.rb +156 -0
  28. data/lib/formtastic/actions/button_action.rb +67 -0
  29. data/lib/formtastic/actions/buttonish.rb +17 -0
  30. data/lib/formtastic/actions/input_action.rb +70 -0
  31. data/lib/formtastic/actions/link_action.rb +88 -0
  32. data/lib/formtastic/deprecation.rb +42 -0
  33. data/lib/formtastic/engine.rb +11 -0
  34. data/lib/formtastic/form_builder.rb +124 -0
  35. data/lib/formtastic/helpers.rb +16 -0
  36. data/lib/formtastic/helpers/action_helper.rb +162 -0
  37. data/lib/formtastic/helpers/actions_helper.rb +168 -0
  38. data/lib/formtastic/helpers/enum.rb +13 -0
  39. data/lib/formtastic/helpers/errors_helper.rb +81 -0
  40. data/lib/formtastic/helpers/fieldset_wrapper.rb +80 -0
  41. data/lib/formtastic/helpers/file_column_detection.rb +16 -0
  42. data/lib/formtastic/helpers/form_helper.rb +203 -0
  43. data/lib/formtastic/helpers/input_helper.rb +407 -0
  44. data/lib/formtastic/helpers/inputs_helper.rb +411 -0
  45. data/lib/formtastic/helpers/reflection.rb +37 -0
  46. data/lib/formtastic/html_attributes.rb +32 -0
  47. data/lib/formtastic/i18n.rb +4 -2
  48. data/lib/formtastic/input_class_finder.rb +18 -0
  49. data/lib/formtastic/inputs.rb +39 -0
  50. data/lib/formtastic/inputs/base.rb +76 -0
  51. data/lib/formtastic/inputs/base/associations.rb +31 -0
  52. data/lib/formtastic/inputs/base/choices.rb +108 -0
  53. data/lib/formtastic/inputs/base/collections.rb +159 -0
  54. data/lib/formtastic/inputs/base/database.rb +22 -0
  55. data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
  56. data/lib/formtastic/inputs/base/errors.rb +58 -0
  57. data/lib/formtastic/inputs/base/fileish.rb +23 -0
  58. data/lib/formtastic/inputs/base/hints.rb +31 -0
  59. data/lib/formtastic/inputs/base/html.rb +53 -0
  60. data/lib/formtastic/inputs/base/labelling.rb +52 -0
  61. data/lib/formtastic/inputs/base/naming.rb +42 -0
  62. data/lib/formtastic/inputs/base/numeric.rb +50 -0
  63. data/lib/formtastic/inputs/base/options.rb +17 -0
  64. data/lib/formtastic/inputs/base/placeholder.rb +17 -0
  65. data/lib/formtastic/inputs/base/stringish.rb +38 -0
  66. data/lib/formtastic/inputs/base/timeish.rb +241 -0
  67. data/lib/formtastic/inputs/base/validations.rb +215 -0
  68. data/lib/formtastic/inputs/base/wrapping.rb +50 -0
  69. data/lib/formtastic/inputs/boolean_input.rb +118 -0
  70. data/lib/formtastic/inputs/check_boxes_input.rb +197 -0
  71. data/lib/formtastic/inputs/color_input.rb +42 -0
  72. data/lib/formtastic/inputs/country_input.rb +86 -0
  73. data/lib/formtastic/inputs/datalist_input.rb +41 -0
  74. data/lib/formtastic/inputs/date_picker_input.rb +93 -0
  75. data/lib/formtastic/inputs/date_select_input.rb +34 -0
  76. data/lib/formtastic/inputs/datetime_picker_input.rb +103 -0
  77. data/lib/formtastic/inputs/datetime_select_input.rb +12 -0
  78. data/lib/formtastic/inputs/email_input.rb +41 -0
  79. data/lib/formtastic/inputs/file_input.rb +42 -0
  80. data/lib/formtastic/inputs/hidden_input.rb +62 -0
  81. data/lib/formtastic/inputs/number_input.rb +88 -0
  82. data/lib/formtastic/inputs/password_input.rb +41 -0
  83. data/lib/formtastic/inputs/phone_input.rb +42 -0
  84. data/lib/formtastic/inputs/radio_input.rb +163 -0
  85. data/lib/formtastic/inputs/range_input.rb +95 -0
  86. data/lib/formtastic/inputs/search_input.rb +41 -0
  87. data/lib/formtastic/inputs/select_input.rb +235 -0
  88. data/lib/formtastic/inputs/string_input.rb +36 -0
  89. data/lib/formtastic/inputs/text_input.rb +48 -0
  90. data/lib/formtastic/inputs/time_picker_input.rb +99 -0
  91. data/lib/formtastic/inputs/time_select_input.rb +38 -0
  92. data/lib/formtastic/inputs/time_zone_input.rb +58 -0
  93. data/lib/formtastic/inputs/url_input.rb +41 -0
  94. data/lib/formtastic/localized_string.rb +17 -0
  95. data/lib/formtastic/localizer.rb +152 -0
  96. data/lib/formtastic/namespaced_class_finder.rb +99 -0
  97. data/lib/formtastic/util.rb +35 -16
  98. data/lib/formtastic/version.rb +3 -0
  99. data/lib/generators/formtastic/form/form_generator.rb +64 -37
  100. data/lib/generators/formtastic/input/input_generator.rb +46 -0
  101. data/lib/generators/formtastic/install/install_generator.rb +13 -5
  102. data/lib/generators/templates/_form.html.erb +10 -4
  103. data/lib/generators/templates/_form.html.haml +8 -4
  104. data/lib/generators/templates/_form.html.slim +8 -0
  105. data/lib/generators/templates/formtastic.rb +77 -44
  106. data/lib/generators/templates/input.rb +19 -0
  107. data/lib/locale/en.yml +3 -0
  108. data/sample/basic_inputs.html +224 -0
  109. data/sample/config.ru +69 -0
  110. data/sample/index.html +14 -0
  111. data/spec/action_class_finder_spec.rb +12 -0
  112. data/spec/actions/button_action_spec.rb +63 -0
  113. data/spec/actions/generic_action_spec.rb +521 -0
  114. data/spec/actions/input_action_spec.rb +59 -0
  115. data/spec/actions/link_action_spec.rb +92 -0
  116. data/spec/builder/custom_builder_spec.rb +116 -0
  117. data/spec/builder/error_proc_spec.rb +27 -0
  118. data/spec/builder/semantic_fields_for_spec.rb +142 -0
  119. data/spec/fast_spec_helper.rb +12 -0
  120. data/spec/generators/formtastic/form/form_generator_spec.rb +131 -0
  121. data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
  122. data/spec/generators/formtastic/install/install_generator_spec.rb +47 -0
  123. data/spec/helpers/action_helper_spec.rb +19 -0
  124. data/spec/helpers/actions_helper_spec.rb +143 -0
  125. data/spec/helpers/form_helper_spec.rb +218 -0
  126. data/spec/helpers/input_helper_spec.rb +6 -0
  127. data/spec/helpers/inputs_helper_spec.rb +655 -0
  128. data/spec/helpers/namespaced_action_helper_spec.rb +43 -0
  129. data/spec/helpers/namespaced_input_helper_spec.rb +36 -0
  130. data/spec/helpers/reflection_helper_spec.rb +32 -0
  131. data/spec/helpers/semantic_errors_helper_spec.rb +112 -0
  132. data/spec/i18n_spec.rb +210 -0
  133. data/spec/input_class_finder_spec.rb +10 -0
  134. data/spec/inputs/base/collections_spec.rb +76 -0
  135. data/spec/inputs/base/validations_spec.rb +342 -0
  136. data/spec/inputs/boolean_input_spec.rb +254 -0
  137. data/spec/inputs/check_boxes_input_spec.rb +546 -0
  138. data/spec/inputs/color_input_spec.rb +97 -0
  139. data/spec/inputs/country_input_spec.rb +133 -0
  140. data/spec/inputs/custom_input_spec.rb +55 -0
  141. data/spec/inputs/datalist_input_spec.rb +61 -0
  142. data/spec/inputs/date_picker_input_spec.rb +449 -0
  143. data/spec/inputs/date_select_input_spec.rb +235 -0
  144. data/spec/inputs/datetime_picker_input_spec.rb +490 -0
  145. data/spec/inputs/datetime_select_input_spec.rb +193 -0
  146. data/spec/inputs/email_input_spec.rb +85 -0
  147. data/spec/inputs/file_input_spec.rb +89 -0
  148. data/spec/inputs/hidden_input_spec.rb +135 -0
  149. data/spec/inputs/include_blank_spec.rb +78 -0
  150. data/spec/inputs/label_spec.rb +149 -0
  151. data/spec/inputs/number_input_spec.rb +815 -0
  152. data/spec/inputs/password_input_spec.rb +99 -0
  153. data/spec/inputs/phone_input_spec.rb +85 -0
  154. data/spec/inputs/placeholder_spec.rb +71 -0
  155. data/spec/inputs/radio_input_spec.rb +328 -0
  156. data/spec/inputs/range_input_spec.rb +505 -0
  157. data/spec/inputs/readonly_spec.rb +50 -0
  158. data/spec/inputs/search_input_spec.rb +84 -0
  159. data/spec/inputs/select_input_spec.rb +615 -0
  160. data/spec/inputs/string_input_spec.rb +260 -0
  161. data/spec/inputs/text_input_spec.rb +187 -0
  162. data/spec/inputs/time_picker_input_spec.rb +455 -0
  163. data/spec/inputs/time_select_input_spec.rb +248 -0
  164. data/spec/inputs/time_zone_input_spec.rb +143 -0
  165. data/spec/inputs/url_input_spec.rb +85 -0
  166. data/spec/inputs/with_options_spec.rb +43 -0
  167. data/spec/localizer_spec.rb +130 -0
  168. data/spec/namespaced_class_finder_spec.rb +79 -0
  169. data/spec/spec.opts +2 -0
  170. data/spec/spec_helper.rb +525 -0
  171. data/spec/support/custom_macros.rb +564 -0
  172. data/spec/support/deprecation.rb +6 -0
  173. data/spec/support/shared_examples.rb +1313 -0
  174. data/spec/support/specialized_class_finder_shared_example.rb +27 -0
  175. data/spec/support/test_environment.rb +31 -0
  176. data/spec/util_spec.rb +66 -0
  177. metadata +434 -161
  178. data/README.textile +0 -682
  179. data/generators/form/USAGE +0 -16
  180. data/generators/form/form_generator.rb +0 -111
  181. data/generators/formtastic/formtastic_generator.rb +0 -26
  182. data/init.rb +0 -5
  183. data/lib/formtastic/layout_helper.rb +0 -12
  184. data/lib/formtastic/railtie.rb +0 -14
  185. data/lib/generators/templates/formtastic.css +0 -145
  186. data/lib/generators/templates/formtastic_changes.css +0 -14
  187. data/lib/generators/templates/rails2/_form.html.erb +0 -5
  188. data/lib/generators/templates/rails2/_form.html.haml +0 -4
  189. data/rails/init.rb +0 -2
@@ -0,0 +1,99 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'password input' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+
12
+ concat(semantic_form_for(@new_post) do |builder|
13
+ concat(builder.input(:title, :as => :password))
14
+ end)
15
+ end
16
+
17
+ it_should_have_input_wrapper_with_class(:password)
18
+ it_should_have_input_wrapper_with_class(:input)
19
+ it_should_have_input_wrapper_with_class(:stringish)
20
+ it_should_have_input_wrapper_with_id("post_title_input")
21
+ it_should_have_label_with_text(/Title/)
22
+ it_should_have_label_for("post_title")
23
+ it_should_have_input_with_id("post_title")
24
+ it_should_have_input_with_type(:password)
25
+ it_should_have_input_with_name("post[title]")
26
+ it_should_have_maxlength_matching_column_limit
27
+ it_should_use_default_text_field_size_when_not_nil(:string)
28
+ it_should_not_use_default_text_field_size_when_nil(:string)
29
+ it_should_apply_custom_input_attributes_when_input_html_provided(:string)
30
+ it_should_apply_custom_for_to_label_when_input_html_id_provided(:string)
31
+ it_should_apply_error_logic_for_input_type(:password)
32
+
33
+ describe "when no object is provided" do
34
+ before do
35
+ concat(semantic_form_for(:project, :url => 'http://test.host/') do |builder|
36
+ concat(builder.input(:title, :as => :password))
37
+ end)
38
+ end
39
+
40
+ it_should_have_label_with_text(/Title/)
41
+ it_should_have_label_for("project_title")
42
+ it_should_have_input_with_id("project_title")
43
+ it_should_have_input_with_type(:password)
44
+ it_should_have_input_with_name("project[title]")
45
+ end
46
+
47
+ describe "when namespace is provided" do
48
+
49
+ before do
50
+ concat(semantic_form_for(@new_post, :namespace => "context2") do |builder|
51
+ concat(builder.input(:title, :as => :password))
52
+ end)
53
+ end
54
+
55
+ it_should_have_input_wrapper_with_id("context2_post_title_input")
56
+ it_should_have_label_and_input_with_id("context2_post_title")
57
+
58
+ end
59
+
60
+ describe "when index is provided" do
61
+
62
+ before do
63
+ @output_buffer = ''
64
+ mock_everything
65
+
66
+ concat(semantic_form_for(@new_post) do |builder|
67
+ concat(builder.fields_for(:author, :index => 3) do |author|
68
+ concat(author.input(:name, :as => :password))
69
+ end)
70
+ end)
71
+ end
72
+
73
+ it 'should index the id of the wrapper' do
74
+ output_buffer.should have_tag("li#post_author_attributes_3_name_input")
75
+ end
76
+
77
+ it 'should index the id of the select tag' do
78
+ output_buffer.should have_tag("input#post_author_attributes_3_name")
79
+ end
80
+
81
+ it 'should index the name of the select tag' do
82
+ output_buffer.should have_tag("input[@name='post[author_attributes][3][name]']")
83
+ end
84
+
85
+ end
86
+
87
+
88
+ describe "when required" do
89
+ it "should add the required attribute to the input's html options" do
90
+ with_config :use_required_attribute, true do
91
+ concat(semantic_form_for(@new_post) do |builder|
92
+ concat(builder.input(:title, :as => :password, :required => true))
93
+ end)
94
+ output_buffer.should have_tag("input[@required]")
95
+ end
96
+ end
97
+ end
98
+
99
+ end
@@ -0,0 +1,85 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'phone input' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ end
12
+
13
+ describe "when object is provided" do
14
+ before do
15
+ concat(semantic_form_for(@new_post) do |builder|
16
+ concat(builder.input(:phone))
17
+ end)
18
+ end
19
+
20
+ it_should_have_input_wrapper_with_class(:phone)
21
+ it_should_have_input_wrapper_with_class(:input)
22
+ it_should_have_input_wrapper_with_class(:stringish)
23
+ it_should_have_input_wrapper_with_id("post_phone_input")
24
+ it_should_have_label_with_text(/Phone/)
25
+ it_should_have_label_for("post_phone")
26
+ it_should_have_input_with_id("post_phone")
27
+ it_should_have_input_with_type(:tel)
28
+ it_should_have_input_with_name("post[phone]")
29
+
30
+ end
31
+
32
+ describe "when namespace is provided" do
33
+
34
+ before do
35
+ concat(semantic_form_for(@new_post, :namespace => "context2") do |builder|
36
+ concat(builder.input(:phone))
37
+ end)
38
+ end
39
+
40
+ it_should_have_input_wrapper_with_id("context2_post_phone_input")
41
+ it_should_have_label_and_input_with_id("context2_post_phone")
42
+
43
+ end
44
+
45
+ describe "when index is provided" do
46
+
47
+ before do
48
+ @output_buffer = ''
49
+ mock_everything
50
+
51
+ concat(semantic_form_for(@new_post) do |builder|
52
+ concat(builder.fields_for(:author, :index => 3) do |author|
53
+ concat(author.input(:name, :as => :phone))
54
+ end)
55
+ end)
56
+ end
57
+
58
+ it 'should index the id of the wrapper' do
59
+ output_buffer.should have_tag("li#post_author_attributes_3_name_input")
60
+ end
61
+
62
+ it 'should index the id of the select tag' do
63
+ output_buffer.should have_tag("input#post_author_attributes_3_name")
64
+ end
65
+
66
+ it 'should index the name of the select tag' do
67
+ output_buffer.should have_tag("input[@name='post[author_attributes][3][name]']")
68
+ end
69
+
70
+ end
71
+
72
+
73
+ describe "when required" do
74
+ it "should add the required attribute to the input's html options" do
75
+ with_config :use_required_attribute, true do
76
+ concat(semantic_form_for(@new_post) do |builder|
77
+ concat(builder.input(:title, :as => :phone, :required => true))
78
+ end)
79
+ output_buffer.should have_tag("input[@required]")
80
+ end
81
+ end
82
+ end
83
+
84
+ end
85
+
@@ -0,0 +1,71 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'string input' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ end
12
+
13
+ after do
14
+ ::I18n.backend.reload!
15
+ end
16
+
17
+ describe "placeholder text" do
18
+
19
+ [:email, :number, :password, :phone, :search, :string, :url, :text, :date_picker, :time_picker, :datetime_picker].each do |type|
20
+
21
+ describe "for #{type} inputs" do
22
+
23
+ describe "when found in i18n" do
24
+ it "should have a placeholder containing i18n text" do
25
+ with_config :i18n_lookups_by_default, true do
26
+ ::I18n.backend.store_translations :en, :formtastic => { :placeholders => { :title => 'War and Peace' }}
27
+ concat(semantic_form_for(@new_post) do |builder|
28
+ concat(builder.input(:title, :as => type))
29
+ end)
30
+ output_buffer.should have_tag((type == :text ? 'textarea' : 'input') + '[@placeholder="War and Peace"]')
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "when not found in i18n" do
36
+ it "should not have placeholder" do
37
+ concat(semantic_form_for(@new_post) do |builder|
38
+ concat(builder.input(:title, :as => type))
39
+ end)
40
+ output_buffer.should_not have_tag((type == :text ? 'textarea' : 'input') + '[@placeholder]')
41
+ end
42
+ end
43
+
44
+ describe "when found in i18n and :input_html" do
45
+ it "should favor :input_html" do
46
+ with_config :i18n_lookups_by_default, true do
47
+ ::I18n.backend.store_translations :en, :formtastic => { :placeholders => { :title => 'War and Peace' }}
48
+ concat(semantic_form_for(@new_post) do |builder|
49
+ concat(builder.input(:title, :as => type, :input_html => { :placeholder => "Foo" }))
50
+ end)
51
+ output_buffer.should have_tag((type == :text ? 'textarea' : 'input') + '[@placeholder="Foo"]')
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "when found in :input_html" do
57
+ it "should use the :input_html placeholder" do
58
+ concat(semantic_form_for(@new_post) do |builder|
59
+ concat(builder.input(:title, :as => type, :input_html => { :placeholder => "Untitled" }))
60
+ end)
61
+ output_buffer.should have_tag((type == :text ? 'textarea' : 'input') + '[@placeholder="Untitled"]')
62
+ end
63
+ end
64
+
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+
71
+ end
@@ -0,0 +1,328 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'radio input' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ end
12
+
13
+ describe 'for belongs_to association' do
14
+ before do
15
+ concat(semantic_form_for(@new_post) do |builder|
16
+ concat(builder.input(:author, :as => :radio, :value_as_class => true, :required => true))
17
+ end)
18
+ end
19
+
20
+ it_should_have_input_wrapper_with_class("radio")
21
+ it_should_have_input_wrapper_with_class(:input)
22
+ it_should_have_input_wrapper_with_id("post_author_input")
23
+ it_should_have_a_nested_fieldset
24
+ it_should_have_a_nested_fieldset_with_class('choices')
25
+ it_should_have_a_nested_ordered_list_with_class('choices-group')
26
+ it_should_apply_error_logic_for_input_type(:radio)
27
+ it_should_use_the_collection_when_provided(:radio, 'input')
28
+
29
+ it 'should generate a legend containing a label with text for the input' do
30
+ output_buffer.should have_tag('form li fieldset legend.label label')
31
+ output_buffer.should have_tag('form li fieldset legend.label label', /Author/)
32
+ end
33
+
34
+ it 'should not link the label within the legend to any input' do
35
+ output_buffer.should_not have_tag('form li fieldset legend label[@for]')
36
+ end
37
+
38
+ it 'should generate an ordered list with a list item for each choice' do
39
+ output_buffer.should have_tag('form li fieldset ol')
40
+ output_buffer.should have_tag('form li fieldset ol li.choice', :count => ::Author.all.size)
41
+ end
42
+
43
+ it 'should have one option with a "checked" attribute' do
44
+ output_buffer.should have_tag('form li input[@checked]', :count => 1)
45
+ end
46
+
47
+ describe "each choice" do
48
+
49
+ it 'should not give the choice label the .label class' do
50
+ output_buffer.should_not have_tag('li.choice label.label')
51
+ end
52
+
53
+ it 'should not add the required attribute to each input' do
54
+ output_buffer.should_not have_tag('li.choice input[@required]')
55
+ end
56
+
57
+
58
+ it 'should contain a label for the radio input with a nested input and label text' do
59
+ ::Author.all.each do |author|
60
+ output_buffer.should have_tag('form li fieldset ol li label', /#{author.to_label}/)
61
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_id_#{author.id}']")
62
+ end
63
+ end
64
+
65
+ it 'should use values as li.class when value_as_class is true' do
66
+ ::Author.all.each do |author|
67
+ output_buffer.should have_tag("form li fieldset ol li.author_#{author.id} label")
68
+ end
69
+ end
70
+
71
+ it "should have a radio input" do
72
+ ::Author.all.each do |author|
73
+ output_buffer.should have_tag("form li fieldset ol li label input#post_author_id_#{author.id}")
74
+ output_buffer.should have_tag("form li fieldset ol li label input[@type='radio']")
75
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='#{author.id}']")
76
+ output_buffer.should have_tag("form li fieldset ol li label input[@name='post[author_id]']")
77
+ end
78
+ end
79
+
80
+ it "should mark input as checked if it's the the existing choice" do
81
+ @new_post.author_id.should == @bob.id
82
+ @new_post.author.id.should == @bob.id
83
+ @new_post.author.should == @bob
84
+
85
+ concat(semantic_form_for(@new_post) do |builder|
86
+ concat(builder.input(:author, :as => :radio))
87
+ end)
88
+
89
+ output_buffer.should have_tag("form li fieldset ol li label input[@checked='checked']")
90
+ end
91
+
92
+ it "should mark the input as disabled if options attached for disabling" do
93
+ concat(semantic_form_for(@new_post) do |builder|
94
+ concat(builder.input(:author, :as => :radio, :collection => [["Test", 'test'], ["Try", "try", {:disabled => true}]]))
95
+ end)
96
+
97
+ output_buffer.should_not have_tag("form li fieldset ol li label input[@value='test'][@disabled='disabled']")
98
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='try'][@disabled='disabled']")
99
+ end
100
+
101
+ it "should not contain invalid HTML attributes" do
102
+
103
+ concat(semantic_form_for(@new_post) do |builder|
104
+ concat(builder.input(:author, :as => :radio))
105
+ end)
106
+
107
+ output_buffer.should_not have_tag("form li fieldset ol li input[@find_options]")
108
+ end
109
+
110
+ end
111
+
112
+ describe 'and no object is given' do
113
+ before(:each) do
114
+ output_buffer.replace ''
115
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
116
+ concat(builder.input(:author_id, :as => :radio, :collection => ::Author.all))
117
+ end)
118
+ end
119
+
120
+ it 'should generate a fieldset with legend' do
121
+ output_buffer.should have_tag('form li fieldset legend', /Author/)
122
+ end
123
+
124
+ it 'should generate an li tag for each item in the collection' do
125
+ output_buffer.should have_tag('form li fieldset ol li', :count => ::Author.all.size)
126
+ end
127
+
128
+ it 'should generate labels for each item' do
129
+ ::Author.all.each do |author|
130
+ output_buffer.should have_tag('form li fieldset ol li label', /#{author.to_label}/)
131
+ output_buffer.should have_tag("form li fieldset ol li label[@for='project_author_id_#{author.id}']")
132
+ end
133
+ end
134
+
135
+ it 'should html escape the label string' do
136
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
137
+ concat(builder.input(:author_id, :as => :radio, :collection => [["<b>Item 1</b>", 1], ["<b>Item 2</b>", 2]]))
138
+ end)
139
+ output_buffer.should have_tag('form li fieldset ol li label') do |label|
140
+ label.body.should match /&lt;b&gt;Item [12]&lt;\/b&gt;$/
141
+ end
142
+ end
143
+
144
+ it 'should generate inputs for each item' do
145
+ ::Author.all.each do |author|
146
+ output_buffer.should have_tag("form li fieldset ol li label input#project_author_id_#{author.id}")
147
+ output_buffer.should have_tag("form li fieldset ol li label input[@type='radio']")
148
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='#{author.id}']")
149
+ output_buffer.should have_tag("form li fieldset ol li label input[@name='project[author_id]']")
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ describe 'for a enum column' do
156
+ before do
157
+ @new_post.stub(:status) { 'inactive' }
158
+ statuses = ActiveSupport::HashWithIndifferentAccess.new("active"=>0, "inactive"=>1)
159
+ @new_post.class.stub(:statuses) { statuses }
160
+ @new_post.stub(:defined_enums) { { "status" => statuses } }
161
+ end
162
+
163
+ before do
164
+ concat(semantic_form_for(@new_post) do |builder|
165
+ concat(builder.input(:status, :as => :radio))
166
+ end)
167
+ end
168
+
169
+ it 'should have a radio input for each defined enum status' do
170
+ output_buffer.should have_tag("form li input[@name='post[status]'][@type='radio']", :count => @new_post.class.statuses.count)
171
+ @new_post.class.statuses.each do |label, value|
172
+ output_buffer.should have_tag("form li input[@value='#{label}']")
173
+ output_buffer.should have_tag("form li label", /#{label.humanize}/)
174
+ end
175
+ end
176
+
177
+ it 'should have one radio input with a "checked" attribute' do
178
+ output_buffer.should have_tag("form li input[@name='post[status]'][@checked]", :count => 1)
179
+ end
180
+ end
181
+
182
+
183
+ describe "with i18n of the legend label" do
184
+
185
+ before do
186
+ ::I18n.backend.store_translations :en, :formtastic => { :labels => { :post => { :authors => "Translated!" }}}
187
+
188
+ with_config :i18n_lookups_by_default, true do
189
+ @new_post.stub(:author_ids).and_return(nil)
190
+ concat(semantic_form_for(@new_post) do |builder|
191
+ concat(builder.input(:authors, :as => :radio))
192
+ end)
193
+ end
194
+ end
195
+
196
+ after do
197
+ ::I18n.backend.reload!
198
+ end
199
+
200
+ it "should do foo" do
201
+ output_buffer.should have_tag("legend.label label", /Translated/)
202
+ end
203
+
204
+ end
205
+
206
+ describe "when :label option is set" do
207
+ before do
208
+ @new_post.stub(:author_ids).and_return(nil)
209
+ concat(semantic_form_for(@new_post) do |builder|
210
+ concat(builder.input(:authors, :as => :radio, :label => 'The authors'))
211
+ end)
212
+ end
213
+
214
+ it "should output the correct label title" do
215
+ output_buffer.should have_tag("legend.label label", /The authors/)
216
+ end
217
+ end
218
+
219
+ describe "when :label option is false" do
220
+ before do
221
+ @output_buffer = ''
222
+ @new_post.stub(:author_ids).and_return(nil)
223
+ concat(semantic_form_for(@new_post) do |builder|
224
+ concat(builder.input(:authors, :as => :radio, :label => false))
225
+ end)
226
+ end
227
+
228
+ it "should not output the legend" do
229
+ output_buffer.should_not have_tag("legend.label")
230
+ output_buffer.should_not include("&gt;")
231
+ end
232
+
233
+ it "should not cause escaped HTML" do
234
+ output_buffer.should_not include("&gt;")
235
+ end
236
+ end
237
+
238
+ describe "when :required option is true" do
239
+ before do
240
+ @new_post.stub(:author_ids).and_return(nil)
241
+ concat(semantic_form_for(@new_post) do |builder|
242
+ concat(builder.input(:authors, :as => :radio, :required => true))
243
+ end)
244
+ end
245
+
246
+ it "should output the correct label title" do
247
+ output_buffer.should have_tag("legend.label label abbr")
248
+ end
249
+ end
250
+
251
+ describe "when :namespace is given on form" do
252
+ before do
253
+ @output_buffer = ''
254
+ @new_post.stub(:author_ids).and_return(nil)
255
+ concat(semantic_form_for(@new_post, :namespace => "custom_prefix") do |builder|
256
+ concat(builder.input(:authors, :as => :radio, :label => ''))
257
+ end)
258
+
259
+ output_buffer.should match(/for="custom_prefix_post_author_ids_(\d+)"/)
260
+ output_buffer.should match(/id="custom_prefix_post_author_ids_(\d+)"/)
261
+ end
262
+ it_should_have_input_wrapper_with_id("custom_prefix_post_authors_input")
263
+ end
264
+
265
+ describe "when index is provided" do
266
+
267
+ before do
268
+ @output_buffer = ''
269
+ mock_everything
270
+
271
+ concat(semantic_form_for(@new_post) do |builder|
272
+ concat(builder.fields_for(:author, :index => 3) do |author|
273
+ concat(author.input(:name, :as => :radio))
274
+ end)
275
+ end)
276
+ end
277
+
278
+ it 'should index the id of the wrapper' do
279
+ output_buffer.should have_tag("li#post_author_attributes_3_name_input")
280
+ end
281
+
282
+ it 'should index the id of the select tag' do
283
+ output_buffer.should have_tag("input#post_author_attributes_3_name_true")
284
+ output_buffer.should have_tag("input#post_author_attributes_3_name_false")
285
+ end
286
+
287
+ it 'should index the name of the select tag' do
288
+ output_buffer.should have_tag("input[@name='post[author_attributes][3][name]']")
289
+ end
290
+
291
+ end
292
+
293
+ describe "when collection contains integers" do
294
+ before do
295
+ @output_buffer = ''
296
+ mock_everything
297
+
298
+ concat(semantic_form_for(:project) do |builder|
299
+ concat(builder.input(:author_id, :as => :radio, :collection => [1, 2, 3]))
300
+ end)
301
+ end
302
+
303
+ it 'should output the correct labels' do
304
+ output_buffer.should have_tag("li.choice label", /1/)
305
+ output_buffer.should have_tag("li.choice label", /2/)
306
+ output_buffer.should have_tag("li.choice label", /3/)
307
+ end
308
+ end
309
+
310
+ describe "when collection contains symbols" do
311
+ before do
312
+ @output_buffer = ''
313
+ mock_everything
314
+
315
+ concat(semantic_form_for(:project) do |builder|
316
+ concat(builder.input(:author_id, :as => :radio, :collection => Set.new([["A", :a], ["B", :b], ["C", :c]])))
317
+ end)
318
+ end
319
+
320
+ it 'should output the correct labels' do
321
+ output_buffer.should have_tag("li.choice label", /A/)
322
+ output_buffer.should have_tag("li.choice label", /B/)
323
+ output_buffer.should have_tag("li.choice label", /C/)
324
+ end
325
+ end
326
+
327
+
328
+ end