merb-helpers 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/LICENSE +20 -0
  2. data/README +180 -0
  3. data/Rakefile +77 -0
  4. data/TODO +5 -0
  5. data/lib/merb-helpers.rb +38 -0
  6. data/lib/merb-helpers/core_ext.rb +57 -0
  7. data/lib/merb-helpers/core_ext/numeric.rb +388 -0
  8. data/lib/merb-helpers/date_time_formatting.rb +127 -0
  9. data/lib/merb-helpers/date_time_helpers.rb +190 -0
  10. data/lib/merb-helpers/form/builder.rb +410 -0
  11. data/lib/merb-helpers/form/helpers.rb +448 -0
  12. data/lib/merb-helpers/form_helpers.rb +24 -0
  13. data/lib/merb-helpers/tag_helpers.rb +61 -0
  14. data/lib/merb-helpers/text_helpers.rb +61 -0
  15. data/lib/merb-helpers/time_dsl.rb +59 -0
  16. data/spec/core_ext_spec.rb +19 -0
  17. data/spec/fixture/app/controllers/application.rb +4 -0
  18. data/spec/fixture/app/controllers/bound_check_box.rb +2 -0
  19. data/spec/fixture/app/controllers/bound_file_field.rb +2 -0
  20. data/spec/fixture/app/controllers/bound_hidden_field.rb +2 -0
  21. data/spec/fixture/app/controllers/bound_option_tag.rb +2 -0
  22. data/spec/fixture/app/controllers/bound_password_field.rb +2 -0
  23. data/spec/fixture/app/controllers/bound_radio_button.rb +2 -0
  24. data/spec/fixture/app/controllers/bound_radio_group.rb +2 -0
  25. data/spec/fixture/app/controllers/bound_select.rb +2 -0
  26. data/spec/fixture/app/controllers/bound_text_area.rb +2 -0
  27. data/spec/fixture/app/controllers/bound_text_field.rb +2 -0
  28. data/spec/fixture/app/controllers/button.rb +2 -0
  29. data/spec/fixture/app/controllers/check_box.rb +2 -0
  30. data/spec/fixture/app/controllers/custom_builder.rb +2 -0
  31. data/spec/fixture/app/controllers/delete_button.rb +2 -0
  32. data/spec/fixture/app/controllers/exceptions.rb +25 -0
  33. data/spec/fixture/app/controllers/field_set.rb +2 -0
  34. data/spec/fixture/app/controllers/fields_for.rb +3 -0
  35. data/spec/fixture/app/controllers/file_field.rb +2 -0
  36. data/spec/fixture/app/controllers/foo.rb +23 -0
  37. data/spec/fixture/app/controllers/form.rb +2 -0
  38. data/spec/fixture/app/controllers/form_for.rb +2 -0
  39. data/spec/fixture/app/controllers/hidden_field.rb +2 -0
  40. data/spec/fixture/app/controllers/label.rb +3 -0
  41. data/spec/fixture/app/controllers/numeric_ext.rb +3 -0
  42. data/spec/fixture/app/controllers/option_tag.rb +2 -0
  43. data/spec/fixture/app/controllers/password_field.rb +2 -0
  44. data/spec/fixture/app/controllers/radio_button.rb +2 -0
  45. data/spec/fixture/app/controllers/radio_group.rb +2 -0
  46. data/spec/fixture/app/controllers/select.rb +2 -0
  47. data/spec/fixture/app/controllers/specs_controller.rb +11 -0
  48. data/spec/fixture/app/controllers/submit.rb +2 -0
  49. data/spec/fixture/app/controllers/tag_helper.rb +21 -0
  50. data/spec/fixture/app/controllers/text_area.rb +2 -0
  51. data/spec/fixture/app/controllers/text_field.rb +3 -0
  52. data/spec/fixture/app/helpers/global_helpers.rb +8 -0
  53. data/spec/fixture/app/models/fake_dm_model.rb +25 -0
  54. data/spec/fixture/app/models/first_generic_fake_model.rb +57 -0
  55. data/spec/fixture/app/models/second_generic_fake_model.rb +18 -0
  56. data/spec/fixture/app/models/third_generic_fake_model.rb +3 -0
  57. data/spec/fixture/app/views/bound_check_box_specs/basic.html.erb +4 -0
  58. data/spec/fixture/app/views/bound_check_box_specs/checked.html.erb +4 -0
  59. data/spec/fixture/app/views/bound_check_box_specs/errors.html.erb +4 -0
  60. data/spec/fixture/app/views/bound_check_box_specs/label.html.erb +3 -0
  61. data/spec/fixture/app/views/bound_check_box_specs/on_and_off.html.erb +3 -0
  62. data/spec/fixture/app/views/bound_check_box_specs/raise_value_error.html.erb +3 -0
  63. data/spec/fixture/app/views/bound_file_field_specs/additional_attributes.html.erb +3 -0
  64. data/spec/fixture/app/views/bound_file_field_specs/takes_string.html.erb +3 -0
  65. data/spec/fixture/app/views/bound_file_field_specs/with_label.html.erb +3 -0
  66. data/spec/fixture/app/views/bound_hidden_field_specs/basic.html.erb +3 -0
  67. data/spec/fixture/app/views/bound_hidden_field_specs/errors.html.erb +3 -0
  68. data/spec/fixture/app/views/bound_hidden_field_specs/hidden_error.html.erb +3 -0
  69. data/spec/fixture/app/views/bound_hidden_field_specs/label.html.erb +3 -0
  70. data/spec/fixture/app/views/bound_option_tag_specs/grouped.html.erb +3 -0
  71. data/spec/fixture/app/views/bound_option_tag_specs/nested.html.erb +3 -0
  72. data/spec/fixture/app/views/bound_option_tag_specs/text_and_value.html.erb +4 -0
  73. data/spec/fixture/app/views/bound_password_field_specs/attributes.html.erb +3 -0
  74. data/spec/fixture/app/views/bound_password_field_specs/basic.html.erb +3 -0
  75. data/spec/fixture/app/views/bound_password_field_specs/label.html.erb +3 -0
  76. data/spec/fixture/app/views/bound_radio_button_specs/basic.html.erb +3 -0
  77. data/spec/fixture/app/views/bound_radio_group_specs/basic.html.erb +3 -0
  78. data/spec/fixture/app/views/bound_radio_group_specs/hashes.html.erb +3 -0
  79. data/spec/fixture/app/views/bound_radio_group_specs/mixed.html.erb +4 -0
  80. data/spec/fixture/app/views/bound_radio_group_specs/override_id.html.erb +3 -0
  81. data/spec/fixture/app/views/bound_select_specs/basic.html.erb +3 -0
  82. data/spec/fixture/app/views/bound_select_specs/blank.html.erb +3 -0
  83. data/spec/fixture/app/views/bound_select_specs/multiple.html.erb +3 -0
  84. data/spec/fixture/app/views/bound_select_specs/prompt.html.erb +3 -0
  85. data/spec/fixture/app/views/bound_select_specs/with_options.html.erb +3 -0
  86. data/spec/fixture/app/views/bound_select_specs/with_options_with_blank.html.erb +3 -0
  87. data/spec/fixture/app/views/bound_text_area_specs/basic.html.erb +3 -0
  88. data/spec/fixture/app/views/bound_text_field_specs/basic.html.erb +3 -0
  89. data/spec/fixture/app/views/button_specs/button_with_label.html.erb +1 -0
  90. data/spec/fixture/app/views/button_specs/button_with_values.html.erb +1 -0
  91. data/spec/fixture/app/views/button_specs/disabled_button.html.erb +1 -0
  92. data/spec/fixture/app/views/check_box_specs/basic.html.erb +1 -0
  93. data/spec/fixture/app/views/check_box_specs/boolean.html.erb +1 -0
  94. data/spec/fixture/app/views/check_box_specs/disabled.html.erb +1 -0
  95. data/spec/fixture/app/views/check_box_specs/label.html.erb +1 -0
  96. data/spec/fixture/app/views/check_box_specs/on_off_is_boolean.html.erb +1 -0
  97. data/spec/fixture/app/views/check_box_specs/raise_unless_both_on_and_off.html.erb +2 -0
  98. data/spec/fixture/app/views/check_box_specs/raises_error_if_not_boolean.html.erb +1 -0
  99. data/spec/fixture/app/views/check_box_specs/raises_error_if_on_off_and_boolean_false.html.erb +1 -0
  100. data/spec/fixture/app/views/check_box_specs/simple.html.erb +1 -0
  101. data/spec/fixture/app/views/check_box_specs/to_string.html.erb +8 -0
  102. data/spec/fixture/app/views/check_box_specs/unchecked.html.erb +2 -0
  103. data/spec/fixture/app/views/custom_builder_specs/everything.html.erb +10 -0
  104. data/spec/fixture/app/views/delete_button_specs/delete_with_explicit_url.html.erb +1 -0
  105. data/spec/fixture/app/views/delete_button_specs/delete_with_extra_params.html.erb +1 -0
  106. data/spec/fixture/app/views/delete_button_specs/delete_with_label.html.erb +1 -0
  107. data/spec/fixture/app/views/delete_button_specs/simple_delete.html.erb +1 -0
  108. data/spec/fixture/app/views/exeptions/client_error.html.erb +37 -0
  109. data/spec/fixture/app/views/exeptions/internal_server_error.html.erb +216 -0
  110. data/spec/fixture/app/views/exeptions/not_acceptable.html.erb +38 -0
  111. data/spec/fixture/app/views/exeptions/not_found.html.erb +40 -0
  112. data/spec/fixture/app/views/fields_for_specs/basic.html.erb +3 -0
  113. data/spec/fixture/app/views/fields_for_specs/midstream.html.erb +7 -0
  114. data/spec/fixture/app/views/fields_for_specs/nil.html.erb +3 -0
  115. data/spec/fixture/app/views/fieldset_specs/legend.html.erb +3 -0
  116. data/spec/fixture/app/views/file_field_specs/disabled.html.erb +1 -0
  117. data/spec/fixture/app/views/file_field_specs/makes_multipart.html.erb +3 -0
  118. data/spec/fixture/app/views/file_field_specs/with_label.html.erb +1 -0
  119. data/spec/fixture/app/views/file_field_specs/with_values.html.erb +1 -0
  120. data/spec/fixture/app/views/foo/bar.html.erb +0 -0
  121. data/spec/fixture/app/views/form_for_specs/basic.html.erb +3 -0
  122. data/spec/fixture/app/views/form_specs/create_a_form.html.erb +3 -0
  123. data/spec/fixture/app/views/form_specs/create_a_multipart_form.html.erb +3 -0
  124. data/spec/fixture/app/views/form_specs/fake_delete_if_set.html.erb +3 -0
  125. data/spec/fixture/app/views/form_specs/fake_put_if_set.html.erb +3 -0
  126. data/spec/fixture/app/views/form_specs/get_if_set.html.erb +3 -0
  127. data/spec/fixture/app/views/form_specs/post_by_default.html.erb +3 -0
  128. data/spec/fixture/app/views/form_specs/resourceful_form.html.erb +3 -0
  129. data/spec/fixture/app/views/hidden_field_specs/basic.html.erb +1 -0
  130. data/spec/fixture/app/views/hidden_field_specs/disabled.html.erb +1 -0
  131. data/spec/fixture/app/views/hidden_field_specs/label.html.erb +1 -0
  132. data/spec/fixture/app/views/label_specs/basic.html.erb +1 -0
  133. data/spec/fixture/app/views/layout/application.html.erb +11 -0
  134. data/spec/fixture/app/views/numeric_ext_specs/minutes_to_hours.html.erb +1 -0
  135. data/spec/fixture/app/views/numeric_ext_specs/to_concurrency_default.html.erb +1 -0
  136. data/spec/fixture/app/views/numeric_ext_specs/two_digits.html.erb +1 -0
  137. data/spec/fixture/app/views/option_tag_specs/array.html.erb +1 -0
  138. data/spec/fixture/app/views/option_tag_specs/clean.html.erb +1 -0
  139. data/spec/fixture/app/views/option_tag_specs/collection.html.erb +1 -0
  140. data/spec/fixture/app/views/option_tag_specs/multiple_selects.html.erb +1 -0
  141. data/spec/fixture/app/views/option_tag_specs/no_extra_attributes.html.erb +1 -0
  142. data/spec/fixture/app/views/option_tag_specs/optgroups.html.erb +1 -0
  143. data/spec/fixture/app/views/option_tag_specs/selected.html.erb +1 -0
  144. data/spec/fixture/app/views/option_tag_specs/with_blank.html.erb +1 -0
  145. data/spec/fixture/app/views/option_tag_specs/with_prompt.html.erb +1 -0
  146. data/spec/fixture/app/views/password_field_specs/basic.html.erb +1 -0
  147. data/spec/fixture/app/views/password_field_specs/disabled.html.erb +1 -0
  148. data/spec/fixture/app/views/radio_button_specs/basic.html.erb +1 -0
  149. data/spec/fixture/app/views/radio_button_specs/disabled.html.erb +1 -0
  150. data/spec/fixture/app/views/radio_button_specs/label.html.erb +1 -0
  151. data/spec/fixture/app/views/radio_group_specs/attributes.html.erb +1 -0
  152. data/spec/fixture/app/views/radio_group_specs/basic.html.erb +1 -0
  153. data/spec/fixture/app/views/radio_group_specs/hash.html.erb +1 -0
  154. data/spec/fixture/app/views/radio_group_specs/specific_attributes.html.erb +1 -0
  155. data/spec/fixture/app/views/select_specs/blank.html.erb +1 -0
  156. data/spec/fixture/app/views/select_specs/multiple.html.erb +1 -0
  157. data/spec/fixture/app/views/submit_specs/disabled_submit.html.erb +1 -0
  158. data/spec/fixture/app/views/submit_specs/submit_with_label.html.erb +1 -0
  159. data/spec/fixture/app/views/submit_specs/submit_with_values.html.erb +1 -0
  160. data/spec/fixture/app/views/tag_helper/nested_tags.html.erb +5 -0
  161. data/spec/fixture/app/views/tag_helper/tag_with_attributes.html.erb +1 -0
  162. data/spec/fixture/app/views/tag_helper/tag_with_content.html.erb +1 -0
  163. data/spec/fixture/app/views/tag_helper/tag_with_content_in_the_block.html.erb +3 -0
  164. data/spec/fixture/app/views/text_area_specs/basic.html.erb +1 -0
  165. data/spec/fixture/app/views/text_area_specs/disabled.html.erb +1 -0
  166. data/spec/fixture/app/views/text_area_specs/label.html.erb +1 -0
  167. data/spec/fixture/app/views/text_area_specs/nil.html.erb +1 -0
  168. data/spec/fixture/app/views/text_field_specs/basic.html.erb +1 -0
  169. data/spec/fixture/app/views/text_field_specs/class.html.erb +1 -0
  170. data/spec/fixture/app/views/text_field_specs/disabled.html.erb +1 -0
  171. data/spec/fixture/app/views/text_field_specs/label.html.erb +1 -0
  172. data/spec/fixture/config/environments/development.rb +6 -0
  173. data/spec/fixture/config/environments/production.rb +5 -0
  174. data/spec/fixture/config/environments/test.rb +6 -0
  175. data/spec/fixture/config/init.rb +46 -0
  176. data/spec/fixture/config/rack.rb +11 -0
  177. data/spec/fixture/config/router.rb +36 -0
  178. data/spec/fixture/log/merb.main.pid +1 -0
  179. data/spec/fixture/log/merb_test.log +624 -0
  180. data/spec/fixture/public/images/merb.jpg +0 -0
  181. data/spec/fixture/public/merb.fcgi +4 -0
  182. data/spec/fixture/public/stylesheets/master.css +119 -0
  183. data/spec/merb_helpers_config_spec.rb +82 -0
  184. data/spec/merb_helpers_date_time_spec.rb +257 -0
  185. data/spec/merb_helpers_form_spec.rb +1266 -0
  186. data/spec/merb_helpers_tag_helper_spec.rb +46 -0
  187. data/spec/merb_helpers_text_spec.rb +67 -0
  188. data/spec/numeric_extlib_spec.rb +135 -0
  189. data/spec/ordinalize_spec.rb +51 -0
  190. data/spec/spec_helper.rb +149 -0
  191. data/spec/time_dsl_spec.rb +43 -0
  192. metadata +303 -0
@@ -0,0 +1,1266 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ # Quick rundown of how these specs work
4
+ # please read before hacking on this plugin
5
+ #
6
+ # helpers must be tested through then entire stack
7
+ # what that means is that each spec must
8
+ # send a request to a controller and render a template
9
+ #
10
+ # Start by creating a spec controller subclassing SpecController
11
+ # which itself is a subclass of Merb::Controller
12
+ # specs_controller.rb (available at spec/fixture/app/controllers/specs_controller.rb)
13
+ # defines SpecController.
14
+ # Create a new controller in the spec/fixture/app/controllers/ if you are adding a new helper
15
+ #
16
+ # To test your helper, start by initializing a controller
17
+ #
18
+ # @controller = CustomHelperSpecs.new(Merb::Request.new({}))
19
+ #
20
+ # Note that we are sending a real request to the controller, feel free to use the request as needed
21
+ #
22
+ # You might need to access real objects in your views
23
+ # you can do that by setting them up in the controller
24
+ #
25
+ # @obj = FakeModel.new # FaKeModel is defined in spec/fixture/models/first_generic_fake_model.rb check it out!
26
+ # @controller.instance_variable_set(:@obj, @obj)
27
+ #
28
+ # To test a helper, you need to render a view:
29
+ #
30
+ # result = @controller.render :view_name
31
+ #
32
+ # Of course, you need to create a view:
33
+ # spec/fixture/app/views/custom_helper_specs/view_name.html.erb
34
+ # in the view, call the helper you want to test
35
+ #
36
+ # You can now test the helper in the view:
37
+ # result.should match_tag(:form, :method => "post")
38
+ #
39
+
40
+
41
+ Merb::Plugins.config[:helpers] = {
42
+ :default_builder => Merb::Helpers::Form::Builder::FormWithErrors
43
+ }
44
+
45
+ Merb::Router.append do
46
+ resources :obj
47
+ end
48
+
49
+
50
+ describe "error_messages_for" do
51
+
52
+ before :each do
53
+ @c = Application.new({})
54
+ @dm_obj = Object.new
55
+ @sq_obj = Object.new
56
+ @dm_errors = [["foo", "bar"],["baz","bat"]]
57
+ @sq_errors = Object.new
58
+ @sq_errors.stub!(:full_messages).and_return(["foo", "baz"])
59
+ @dm_obj.stub!(:errors).and_return(@dm_errors)
60
+ @dm_obj.stub!(:new_record?).and_return(false)
61
+ @sq_obj.stub!(:errors).and_return(@sq_errors)
62
+ @sq_obj.stub!(:new_record?).and_return(false)
63
+ end
64
+
65
+ it "should build default error messages for AR-like models" do
66
+ errs = @c.error_messages_for(@dm_obj)
67
+ errs.should include("<h2>Form submission failed because of 2 problems</h2>")
68
+ errs.should include("<li>foo bar</li>")
69
+ errs.should include("<li>baz bat</li>")
70
+ end
71
+
72
+ it "should build default error messages for Sequel-like models" do
73
+ errs = @c.error_messages_for(@sq_obj)
74
+ errs.should include("<h2>Form submission failed because of 2 problems</h2>")
75
+ errs.should include("<li>foo</li>")
76
+ errs.should include("<li>baz</li>")
77
+ end
78
+
79
+ # it "should build default error messages for symbol" do
80
+ # errs = error_messages_for(:obj)
81
+ # errs.should include("<h2>Form submittal failed because of 2 problems</h2>")
82
+ # errs.should include("<li>foo bar</li>")
83
+ # errs.should include("<li>baz bat</li>")
84
+ # end
85
+
86
+ it "should accept a custom HTML class" do
87
+ errs = @c.error_messages_for(@dm_obj, :error_class => "foo")
88
+ errs.should include("<div class='foo'>")
89
+ end
90
+
91
+ it "should accept a custom header block" do
92
+ errs = @c.error_messages_for(@dm_obj, :header => "<h3>Failure: %s issue%s</h3>")
93
+ errs.should include("<h3>Failure: 2 issues</h3>")
94
+ end
95
+
96
+ # it "should put the error messages inside a form if :before is false" do
97
+ # ret = @c.form_for @dm_obj do
98
+ # _buffer << error_messages
99
+ # end
100
+ # ret.should =~ /\A\s*<form.*<div class='error'>/
101
+ # end
102
+
103
+ end
104
+
105
+ describe "form" do
106
+
107
+ before :each do
108
+ @c = FormSpecs.new(Merb::Request.new({}))
109
+ end
110
+
111
+ describe "when _default_builder is Merb::Helpers::Form::Builder::ResourcefulFormWithErrors" do
112
+
113
+ before(:each) do
114
+ @obj = FakeModel2.new
115
+ @c.instance_variable_set(:@obj, @obj)
116
+ end
117
+
118
+ it "should not explode when #form is called" do
119
+ r = @c.render :resourceful_form
120
+ pending
121
+ #r.should =~ /action="fake_model2\/#{@obj.id}"/
122
+ end
123
+ end
124
+
125
+
126
+ it "should use the post method by default" do
127
+ ret = @c.render(:post_by_default)
128
+ ret.should match_tag(:form, :method => "post")
129
+ ret.should include("CONTENT")
130
+ end
131
+
132
+ it "should use the get method if set" do
133
+ ret = @c.render(:get_if_set)
134
+ ret.should match_tag(:form, :method => "get")
135
+ end
136
+
137
+ it "should fake out the put method if set" do
138
+ ret = @c.render(:fake_put_if_set)
139
+ ret.should match_tag(:form, :method => "post")
140
+ ret.should match_tag(:input, :type => "hidden", :name => "_method", :value => "put")
141
+ end
142
+
143
+ it "should fake out the delete method if set" do
144
+ ret = @c.render(:fake_delete_if_set)
145
+ ret.should match_tag(:form, :method => "post")
146
+ ret.should match_tag(:input, :type => "hidden", :name => "_method", :value => "delete")
147
+ end
148
+
149
+ # TODO: Why is this required?
150
+ # ---------------------------
151
+ #
152
+ # it "should silently set method to post if an unsupported method is used" do
153
+ # form_tag :method => :dodgy do
154
+ # _buffer << "CONTENT"
155
+ # end
156
+ # _buffer.should match_tag(:form, :method => "post")
157
+ # _buffer.should_not match_tag(:input, :type => "hidden", :name => "_method", :value => "dodgy")
158
+ # end
159
+
160
+ it "should take create a form" do
161
+ ret = @c.render(:create_a_form)
162
+ ret.should match_tag(:form, :action => "foo", :method => "post")
163
+ ret.should include("Hello")
164
+ end
165
+
166
+ it "should set a form to be multipart" do
167
+ ret = @c.render(:create_a_multipart_form)
168
+ ret.should match_tag( :form, :action => "foo", :method => "post", :enctype => "multipart/form-data")
169
+ ret.should include("CONTENT")
170
+ end
171
+ end
172
+
173
+
174
+ describe "form_for" do
175
+
176
+ before :each do
177
+ @c = FormForSpecs.new(Merb::Request.new({}))
178
+ @c.instance_variable_set(:@obj, FakeModel.new)
179
+ end
180
+
181
+ it "should wrap the contents in a form tag" do
182
+ form = @c.render :basic
183
+ form.should match_tag(:form, :method => "post")
184
+ form.should match_tag(:input, :type => "hidden", :value => "put", :name => "_method")
185
+ end
186
+
187
+ it "should set the method to post be default" do
188
+ new_fake_model = FakeModel2.new
189
+ @c.instance_variable_set(:@obj, new_fake_model)
190
+ form = @c.render :basic
191
+ form.should match_tag(:form, :method => "post")
192
+ form.should_not match_tag(:input, :type => "hidden", :name => "_method")
193
+ end
194
+
195
+ it "should support PUT if the object passed in is not a new_record? via a hidden field" do
196
+ form = @c.render :basic
197
+ form.should match_tag(:form, :method => "post")
198
+ form.should match_tag(:input, :type => "hidden", :value => "put", :name => "_method")
199
+ end
200
+
201
+ end
202
+
203
+
204
+ describe "fields_for" do
205
+
206
+ before :each do
207
+ @c = FieldsForSpecs.new(Merb::Request.new({}))
208
+ @c.instance_variable_set(:@obj, FakeModel.new)
209
+ end
210
+
211
+
212
+ it "should dump the contents in the context of the object" do
213
+ r = @c.render :basic
214
+ r.should match_tag(:input, :type => "text", :value => "foowee")
215
+ end
216
+
217
+ it "should be able to modify the context midstream" do
218
+ @c.instance_variable_set(:@obj2, FakeModel2.new)
219
+ r = @c.render :midstream
220
+ r.should match_tag(:input, :type => "text", :value => "foowee")
221
+ r.should match_tag(:input, :name => "fake_model2[foo]", :type => "text", :value => "foowee2")
222
+ end
223
+
224
+ it "should handle an explicit nil attribute" do
225
+ r = @c.render :nil
226
+ r.should match_tag(:input, :name => "fake_model[foo]", :value => "foowee", :type => "text")
227
+ end
228
+
229
+ it "should pass context back to the old object after exiting block" do
230
+ @c.instance_variable_set(:@obj2, FakeModel2.new)
231
+ r = @c.render :midstream
232
+ r.should match_tag(:input, :id => "fake_model_foo", :name => "fake_model[foo]", :type => "text", :extra => "true")
233
+ end
234
+ end
235
+
236
+ describe "text_field" do
237
+
238
+ before :each do
239
+ @c = TextFieldSpecs.new(Merb::Request.new({}))
240
+ end
241
+
242
+ it "should return a basic text field based on the values passed in" do
243
+ r = @c.render :basic
244
+ r.should match_tag( :input, :type => "text", :name => "foo", :value => "bar")
245
+ end
246
+
247
+ it "should provide an additional label tag if the :label option is passed in" do
248
+ r = @c.render :basic
249
+ r.should match(/<label>LABEL<\/label>/)
250
+ end
251
+
252
+ it "should update an existing :class with a new class" do
253
+ r = @c.render :class
254
+ r.should == "<input type=\"text\" class=\"awesome foobar text\"/>"
255
+ end
256
+
257
+ it "should be disabled if :disabled => true is passed in" do
258
+ r = @c.render :disabled
259
+ r.should match_tag(:input, :type => "text", :disabled => "disabled")
260
+ end
261
+
262
+ it "should provide an additional label tag if the :label option is passed in as a hash" do
263
+ r = @c.render :label
264
+ r.should match(/<label class="cool">LABEL<\/label>/)
265
+ end
266
+
267
+ end
268
+
269
+ describe "bound_text_field" do
270
+
271
+ before :each do
272
+ @c = BoundTextFieldSpecs.new(Merb::Request.new({}))
273
+ @c.instance_variable_set(:@obj, FakeModel.new)
274
+ end
275
+
276
+ it "should take a string object and return a useful text control" do
277
+ r = @c.render :basic
278
+ r.should match_tag(:input, :type => "text", :name => "fake_model[foo]", :value => "foowee")
279
+ end
280
+
281
+ it "should take additional attributes and use them" do
282
+ r = @c.render :basic
283
+ r.should match_tag(:input, :type => "text", :name => "fake_model[foo]", :value => "foowee", :bar => "7")
284
+ end
285
+
286
+ it "should provide an additional label tag if the :label option is passed in" do
287
+ form = @c.render :basic
288
+ form.should match(/<label.*>LABEL<\/label><input/)
289
+ res = form.scan(/<[^>]*>/)
290
+ res[2].should_not match_tag(:input, :label => "LABEL")
291
+ end
292
+
293
+ it "should not errorify the field for a new object" do
294
+ r = @c.render :basic
295
+ r.should_not match_tag(:input, :type => "text", :name => "fake_model[foo]", :class => "error")
296
+ end
297
+
298
+ it "should errorify a field for a model with errors" do
299
+ model = mock("model")
300
+ model.stub!(:new_record?).and_return(true)
301
+ model.stub!(:class).and_return("MyClass")
302
+ model.stub!(:foo).and_return("FOO")
303
+ errors = mock("errors")
304
+ errors.should_receive(:on).with(:foo).and_return(true)
305
+
306
+ model.stub!(:errors).and_return(errors)
307
+ @c.instance_variable_set(:@obj, model)
308
+ r = @c.render :basic
309
+ r.should match_tag(:input, :class => "error text")
310
+ end
311
+ end
312
+
313
+ describe "bound_radio_button" do
314
+
315
+ before :each do
316
+ @c = BoundRadioButtonSpecs.new(Merb::Request.new({}))
317
+ @c.instance_variable_set(:@obj, FakeModel.new)
318
+ end
319
+
320
+ it "should take a string object and return a useful text control" do
321
+ r = @c.render :basic
322
+ r.should match_tag(:input, :type => "radio", :name => "fake_model[foo]", :value => "foowee")
323
+ end
324
+
325
+ it "should take additional attributes and use them" do
326
+ r = @c.render :basic
327
+ r.should match_tag(:input, :type => "radio", :name => "fake_model[foo]", :value => "foowee", :bar => "7")
328
+ end
329
+
330
+ it "should provide an additional label tag if the :label option is passed in" do
331
+ form = @c.render :basic
332
+ form.should match(/<input.*><label.*>LABEL<\/label>/)
333
+ res = form.scan(/<[^>]*>/)
334
+ res[2].should_not match_tag(:input, :label => "LABEL")
335
+ end
336
+
337
+ it "should not errorify the field for a new object" do
338
+ r = @c.render :basic
339
+ r.should_not match_tag(:input, :type => "radio", :name => "fake_model[foo]", :class => "error")
340
+ end
341
+
342
+ it "should errorify a field for a model with errors" do
343
+ model = mock("model")
344
+ model.stub!(:new_record?).and_return(true)
345
+ model.stub!(:class).and_return("MyClass")
346
+ model.stub!(:foo).and_return("FOO")
347
+ errors = mock("errors")
348
+ errors.should_receive(:on).with(:foo).and_return(true)
349
+
350
+ model.stub!(:errors).and_return(errors)
351
+ @c.instance_variable_set(:@obj, model)
352
+ r = @c.render :basic
353
+ r.should match_tag(:input, :class => "error radio")
354
+ end
355
+ end
356
+
357
+ describe "password_field" do
358
+
359
+ before :each do
360
+ @c = PasswordFieldSpecs.new(Merb::Request.new({}))
361
+ end
362
+
363
+ it "should return a basic password field, but omit the value" do
364
+ r = @c.render :basic
365
+ r.should match_tag(:input, :type => "password", :name => "foo")
366
+ end
367
+
368
+ it "should provide an additional label tag if the :label option is passed in" do
369
+ r = @c.render :basic
370
+ r.should match(/<label.*>LABEL<\/label>/)
371
+ end
372
+
373
+ it "should be disabled if :disabled => true is passed in" do
374
+ r = @c.render :disabled
375
+ r.should match_tag(:input, :type => "password", :disabled => "disabled")
376
+ end
377
+ end
378
+
379
+ describe "bound_password_field" do
380
+
381
+ before :each do
382
+ @c = BoundPasswordFieldSpecs.new(Merb::Request.new({}))
383
+ @obj = FakeModel.new
384
+ @c.instance_variable_set(:@obj, @obj)
385
+ end
386
+
387
+ it "should take a string object and return a useful password control, but omit the value" do
388
+ r = @c.render :basic
389
+ r.should match_tag(:input, :type => "password", :name => "fake_model[foo]")
390
+ end
391
+
392
+ it "should take additional attributes and use them" do
393
+ r = @c.render :basic
394
+ r.should match_tag(:input, :type => "password", :name => "fake_model[foo]", :bar => "7", :value => @obj.foo)
395
+ end
396
+
397
+ it "should provide an additional label tag if the :label option is passed in" do
398
+ r = @c.render :basic
399
+ r.should match(/<label.*>LABEL<\/label><input/)
400
+ res = r.scan(/<[^>]*>/)
401
+ res[2].should_not match_tag(:input, :label => "LABEL")
402
+ end
403
+
404
+ it "should not errorify the field for a new object" do
405
+ r = @c.render :basic
406
+ r.should_not match_tag(:input, :class => "error")
407
+ end
408
+
409
+ it "should errorify a field for a model with errors" do
410
+ model = mock("model")
411
+ model.stub!(:new_record?).and_return(true)
412
+ model.stub!(:class).and_return("MyClass")
413
+ model.stub!(:foo).and_return("FOO")
414
+ errors = mock("errors")
415
+ errors.should_receive(:on).with(:foo).and_return(true)
416
+
417
+ model.stub!(:errors).and_return(errors)
418
+
419
+ @c.instance_variable_set(:@obj, model)
420
+ r = @c.render :basic
421
+ r.should match_tag(:input, :class => "error password")
422
+ end
423
+
424
+ end
425
+
426
+ describe "check_box" do
427
+
428
+ before :each do
429
+ @c = CheckBoxSpecs.new(Merb::Request.new({}))
430
+ end
431
+
432
+ it "should return a basic checkbox based on the values passed in" do
433
+ r = @c.render :basic
434
+ r.should match_tag(:input, :class => "checkbox", :name => "foo", :checked => "checked")
435
+ end
436
+
437
+ it "should provide an additional label tag if the :label option is passed in" do
438
+ result = @c.render :label
439
+ result.should match(/<input.*><label>LABEL<\/label>/)
440
+ res = result.scan(/<[^>]*>/)
441
+ res[0].should_not match_tag(:input, :label => "LABEL")
442
+ end
443
+
444
+ it 'should remove the checked="checked" attribute if :checked is false or nil' do
445
+ r = @c.render :unchecked
446
+ r.should_not include('checked="')
447
+ end
448
+
449
+ it 'should have the checked="checked" attribute if :checked => true is passed in' do
450
+ r = @c.render :basic
451
+ r.should include('checked="checked"')
452
+ end
453
+
454
+ it "should not be boolean by default" do
455
+ r = @c.render :basic
456
+ r.should match_tag(:input, :type => "checkbox", :name => "foo")
457
+ end
458
+
459
+ it "should add a hidden input if boolean" do
460
+ r = @c.render :boolean
461
+ r.should have_tag(:input, :type => "checkbox", :value => "1")
462
+ r.should have_tag(:input, :type => "hidden", :value => "0")
463
+ r.should match(/<input.*?type="hidden"[^>]*>[^<]*<input.*?type="checkbox"[^>]*>/)
464
+
465
+ end
466
+
467
+ it "should not allow a :value param if boolean" do
468
+ lambda { @c.render :raises_error_if_not_boolean }.
469
+ should raise_error(ArgumentError, /can't be used with a boolean checkbox/)
470
+ end
471
+
472
+ it "should not allow :boolean => false if :on and :off are specified" do
473
+ lambda { @c.render :raises_error_if_on_off_and_boolean_false }.
474
+ should raise_error(ArgumentError, /cannot be used/)
475
+ end
476
+
477
+ it "should be boolean if :on and :off are specified" do
478
+ html = @c.render :on_off_is_boolean
479
+ html.should have_tag(:input, :type => "checkbox", :value => "YES", :name => "foo")
480
+ html.should have_tag(:input, :type => "hidden", :value => "NO", :name => "foo")
481
+ end
482
+
483
+ it "should have both :on and :off specified or neither" do
484
+ lambda { @c.render :raise_unless_both_on_and_off }.should raise_error(ArgumentError, /must be specified/)
485
+ lambda { @c.render :raise_unless_both_on_and_off }.should raise_error(ArgumentError, /must be specified/)
486
+ end
487
+
488
+ it "should convert :value to a string on a non-boolean checkbox" do
489
+ r = @c.render :to_string
490
+ r.should match_tag(:input, :value => "")
491
+ r.should match_tag(:input, :value => "false")
492
+ r.should match_tag(:input, :value => "0")
493
+ r.should match_tag(:input, :value => "0")
494
+ r.should match_tag(:input, :value => "1")
495
+ r.should match_tag(:input, :value => "1")
496
+ r.should match_tag(:input, :value => "true")
497
+ end
498
+
499
+ it "should be disabled if :disabled => true is passed in" do
500
+ r = @c.render :disabled
501
+ r.should match_tag(:input, :type => "checkbox", :disabled => "disabled")
502
+ end
503
+
504
+ it "should be possible to call with just check_box" do
505
+ r = @c.render :simple
506
+ r.should match_tag(:input, :type => "checkbox", :class => "checkbox")
507
+ end
508
+ end
509
+
510
+ describe "bound_check_box" do
511
+
512
+ before :each do
513
+ @c = BoundCheckBoxSpecs.new(Merb::Request.new({}))
514
+ @c.instance_variable_set(:@obj, FakeModel.new)
515
+ end
516
+
517
+ it "should take a string and return a useful checkbox control" do
518
+ r = @c.render :basic
519
+ r.should match_tag(:input, :type =>"checkbox", :name => "fake_model[baz]", :class => "checkbox", :value => "1", :checked => "checked", :id => "fake_model_baz")
520
+ r.should match_tag(:input, :type =>"checkbox", :name => "fake_model[bat]", :class => "checkbox", :value => "0")
521
+ end
522
+
523
+ it "should raise an error if you try to use :value" do
524
+ lambda { @c.render(:raise_value_error) }.should raise_error(ArgumentError, /:value can't be used with a bound_check_box/)
525
+ end
526
+
527
+ it "should support models from datamapper" do
528
+ @c.instance_variable_set(:@obj, FakeDMModel.new)
529
+ r = @c.render :basic
530
+ r.should match_tag(:input,
531
+ :type =>"checkbox",
532
+ :name => "fake_dm_model[baz]",
533
+ :class => "checkbox",
534
+ :value => "1",
535
+ :checked => "checked",
536
+ :id => "fake_dm_model_baz")
537
+ r.should match_tag(:input, :type =>"checkbox", :name => "fake_dm_model[bat]", :class => "checkbox", :value => "0")
538
+ end
539
+
540
+ it "should allow a user to set the :off value" do
541
+ r = @c.render :on_and_off
542
+ r.should match_tag(:input, :type =>"checkbox", :name => "fake_model[bat]", :class => "checkbox", :value => "off")
543
+ end
544
+
545
+ it "should render controls with errors if their attribute contains an error" do
546
+ r = @c.render :errors
547
+ r.should match_tag(:input, :type =>"checkbox", :name => "fake_model[bazbad]", :class => "error checkbox", :value => "1", :checked => "checked")
548
+ r.should match_tag(:input, :type =>"checkbox", :name => "fake_model[batbad]", :class => "error checkbox", :value => "0")
549
+ end
550
+
551
+ it "should provide an additional label tag if the :label option is passed in" do
552
+ form = @c.render :label
553
+ form.should match( /<input.*><label.*>LABEL<\/label>/ )
554
+ res = form.scan(/<[^>]*>/)
555
+ res[0].should_not match_tag(:input, :label => "LABEL")
556
+ end
557
+
558
+ it "should not errorify the field for a new object" do
559
+ r = @c.render :basic
560
+ r.should_not match_tag(:input, :type => "checkbox", :class => "error checkbox")
561
+ end
562
+
563
+ it "should errorify a field for a model with errors" do
564
+ model = mock("model")
565
+ model.stub!(:new_record?).and_return(true)
566
+ model.stub!(:class).and_return("MyClass")
567
+ model.stub!(:baz).and_return("BAZ")
568
+ model.stub!(:bat).and_return("BAT")
569
+ errors = mock("errors")
570
+ errors.should_receive(:on).with(:baz).and_return(true)
571
+ errors.should_receive(:on).with(:bat).and_return(true)
572
+
573
+ model.stub!(:errors).and_return(errors)
574
+
575
+ @c.instance_variable_set(:@obj, model)
576
+ r = @c.render :basic
577
+ r.should match_tag(:input, :type => "checkbox", :class => "error checkbox")
578
+ end
579
+
580
+ it "should be boolean" do
581
+ r = @c.render :basic
582
+ r.should have_tag(:input, :type => "checkbox", :value => "1")
583
+ r.should have_tag(:input, :type => "hidden", :value => "0")
584
+ end
585
+
586
+ it "should be checked if the value of the model's attribute is equal to the value of :on" do
587
+ r = @c.render :checked
588
+ r.should match_tag(:input, :type =>"checkbox", :value => "foowee", :checked => "checked")
589
+ r.should match_tag(:input, :type =>"checkbox", :value => "YES", :checked => "checked")
590
+
591
+ end
592
+ end
593
+
594
+ describe "hidden_field" do
595
+
596
+ before :each do
597
+ @c = HiddenFieldSpecs.new(Merb::Request.new({}))
598
+ end
599
+
600
+ it "should return a basic checkbox based on the values passed in" do
601
+ r = @c.render :basic
602
+ r.should match_tag(:input, :type => "hidden", :name => "foo", :value => "bar")
603
+ end
604
+
605
+ it "should not render a label if the :label option is passed in" do
606
+ res = @c.render :label
607
+ res.should_not match(/<label>LABEL/)
608
+ res.should_not match_tag(:input, :label=> "LABEL")
609
+ end
610
+
611
+ it "should be disabled if :disabled => true is passed in" do
612
+ r = @c.render :disabled
613
+ r.should match_tag(:input, :type => "hidden", :disabled => "disabled")
614
+ end
615
+ end
616
+
617
+ describe "bound_hidden_field" do
618
+
619
+ before :each do
620
+ @c = BoundHiddenFieldSpecs.new(Merb::Request.new({}))
621
+ @c.instance_variable_set(:@obj, FakeModel.new)
622
+ end
623
+
624
+ it "should take a string and return a hidden field control" do
625
+ r = @c.render :basic
626
+ r.should match_tag(:input, :type =>"hidden", :name => "fake_model[foo]", :value => "foowee")
627
+ end
628
+
629
+ it "should render controls with errors if their attribute contains an error" do
630
+ r = @c.render :errors
631
+ r.should match_tag(:input, :type =>"hidden", :name => "fake_model[foobad]", :value => "foowee", :class => "error hidden")
632
+ end
633
+
634
+ it "should not render a label if the :label option is passed in" do
635
+ r = @c.render :label
636
+ r.should_not match(/<label>LABEL/)
637
+ r.should_not match_tag(:input, :label=> "LABEL")
638
+ end
639
+
640
+ it "should not errorify the field for a new object" do
641
+ r = @c.render :basic
642
+ r.should_not match_tag(:input, :type => "hidden", :class => "error")
643
+ end
644
+
645
+ it "should not errorify a field for a model with errors" do
646
+ model = mock("model")
647
+ model.stub!(:new_record?).and_return(true)
648
+ model.stub!(:class).and_return("MyClass")
649
+ model.stub!(:foo).and_return("FOO")
650
+ errors = mock("errors")
651
+ errors.should_receive(:on).with(:foo).and_return(true)
652
+
653
+ model.stub!(:errors).and_return(errors)
654
+
655
+ Merb::Router.append do
656
+ resources :models
657
+ end
658
+
659
+ @c.instance_variable_set(:@model, model)
660
+ r = @c.render :hidden_error
661
+ r.should match_tag(:input, :type => "hidden", :name => "my_class[foo]", :class => "error hidden")
662
+ end
663
+
664
+ end
665
+
666
+ describe "radio_button" do
667
+
668
+ before :each do
669
+ @c = RadioButtonSpecs.new(Merb::Request.new({}))
670
+ end
671
+
672
+ it "should should return a basic radio button based on the values passed in" do
673
+ r = @c.render :basic
674
+ r.should match_tag(:input, :type => "radio", :name => "foo", :value => "bar", :id => "baz")
675
+ end
676
+
677
+ it "should provide an additional label tag if the :label option is passed in" do
678
+ result = @c.render :label
679
+ # result.should match(/<label.*>LABEL<\/label><input/)
680
+ # res = result.scan(/<[^>]*>/)
681
+ # res[2].should_not match_tag(:input, :label => "LABEL")
682
+ result.should match(/<input.*><label.*>LABEL<\/label>/)
683
+ res = result.scan(/<[^>]*>/)
684
+ res[0].should_not match_tag(:input, :label => "LABEL")
685
+ end
686
+
687
+ it "should be disabled if :disabled => true is passed in" do
688
+ r = @c.render :disabled
689
+ r.should match_tag(:input, :type => "radio", :disabled => "disabled")
690
+ end
691
+ end
692
+
693
+ describe "radio_group" do
694
+
695
+ before :each do
696
+ @c = RadioGroupSpecs.new(Merb::Request.new({}))
697
+ end
698
+
699
+ it "should return a group of radio buttons" do
700
+ radio = @c.render :basic
701
+ radio = radio.scan(/<[^>]*>/)
702
+ radio[0].should match_tag(:input, :type => "radio", :value => "foowee")
703
+ radio[3].should match_tag(:input, :type => "radio", :value => "baree")
704
+ end
705
+
706
+ it "should provide an additional label tag for each option in array-based options" do
707
+ radio = @c.render :basic
708
+ radio.scan( /<input.*?><label.*?>(foowee|baree)<\/label>/ ).size.should == 2
709
+ radio = radio.scan(/<[^>]*>/)
710
+ radio[0].should_not match_tag(:input, :label => "LABEL")
711
+ radio[3].should_not match_tag(:input, :label => "LABEL")
712
+ end
713
+
714
+ it "should accept array of hashes as options" do
715
+ radio = @c.render :hash
716
+ radio.scan( /<input.*?><label.*?>(Five|Bar)<\/label>/ ).size.should == 2
717
+ radio = radio.scan(/<[^>]*>/)
718
+ radio.size.should == 6
719
+ radio[0].should match_tag(:input, :value => 5)
720
+ radio[1].should match_tag(:label)
721
+ radio[2].should match_tag('/label')
722
+ radio[3].should match_tag(:input, :value => 'bar', :id => 'bar_id')
723
+ radio[4].should match_tag(:label, :for => 'bar_id')
724
+ radio[5].should match_tag('/label')
725
+ end
726
+
727
+ it "should apply attributes to each element" do
728
+ radio = @c.render :attributes
729
+ radio = radio.scan(/<[^>]*>/)
730
+ radio[0].should match_tag(:input, :type => "radio", :value => "foowee", :class => "CLASS radio")
731
+ radio[3].should match_tag(:input, :type => "radio", :value => "baree", :class => "CLASS radio")
732
+ end
733
+
734
+ it "should override universal attributes with specific ones" do
735
+ radio = @c.render :specific_attributes
736
+ radio = radio.scan(/<[^>]*>/)
737
+ radio[0].should match_tag(:input, :type => "radio", :value => "foowee", :class => "CLASS radio")
738
+ radio[3].should match_tag(:input, :type => "radio", :value => "baree", :class => "BAREE radio")
739
+ end
740
+ end
741
+
742
+
743
+ describe "bound_radio_group" do
744
+
745
+ before do
746
+ @c = BoundRadioGroupSpecs.new(Merb::Request.new({}))
747
+ @c.instance_variable_set(:@obj, FakeModel.new)
748
+ end
749
+
750
+ it "should return a group of radio buttons" do
751
+ r = @c.render :basic
752
+ radio = r.scan(/<[^>]*>/)
753
+ radio[2].should match_tag(:input, :type => "radio", :name => "fake_model[foo]", :value => "foowee", :checked => "checked")
754
+ radio[5].should match_tag(:input, :type => "radio", :name => "fake_model[foo]", :value => "baree")
755
+ radio[6].should not_match_tag(:checked => "checked")
756
+ end
757
+
758
+ it "should provide an additional label tag for each option in array-based options" do
759
+ r = @c.render :basic
760
+ r.scan( /<input.*?><label.*?>(foowee|baree)<\/label>/ ).size.should == 2
761
+ radio = r.scan(/<[^>]*>/)[2..-2]
762
+ radio[0].should_not match_tag(:input, :label => "LABEL")
763
+ radio[3].should_not match_tag(:input, :label => "LABEL")
764
+ end
765
+
766
+ it "should accept array of hashes as options" do
767
+ r = @c.render :hashes
768
+ r.scan( /<input.*?><label.*?>(Five|Bar)<\/label>/ ).size.should == 2
769
+ radio = r.scan(/<[^>]*>/)[2..-2]
770
+ radio.size.should == 6
771
+ radio[0].should match_tag(:input, :value => 5)
772
+ radio[1].should match_tag(:label)
773
+ radio[2].should match_tag('/label')
774
+ radio[3].should match_tag(:input, :value => 'bar', :id => 'bar_id')
775
+ radio[4].should match_tag(:label, :for => 'bar_id')
776
+ radio[5].should match_tag('/label')
777
+ end
778
+
779
+ it "should provide autogenerated id for inputs" do
780
+ r = @c.render :mixed
781
+ radio = r.scan(/<[^>]*>/)[2..-2]
782
+ pp radio
783
+ radio[0].should match_tag(:input, :id => 'fake_model_foo_bar')
784
+ radio[1].should match_tag(:label, :for => 'fake_model_foo_bar')
785
+ radio[3].should match_tag(:input, :id => 'fake_model_foo_bar')
786
+ radio[4].should match_tag(:label, :for => 'fake_model_foo_bar')
787
+ end
788
+
789
+ it "should override autogenerated id for inputs with hash-given id" do
790
+ r = @c.render :override_id
791
+ radio = r.scan(/<[^>]*>/)[2..-2]
792
+ radio[0].should match_tag(:input, :id => 'bar_id')
793
+ radio[1].should match_tag(:label, :for => 'bar_id')
794
+ end
795
+ end
796
+
797
+
798
+ describe "text_area" do
799
+
800
+ before do
801
+ @c = TextAreaSpecs.new(Merb::Request.new({}))
802
+ end
803
+
804
+ it "should should return a basic text area based on the values passed in" do
805
+ r = @c.render :basic
806
+ r.should match_tag(:textarea, :name => "foo")
807
+ end
808
+
809
+ it "should handle a nil content" do
810
+ r = @c.render :nil
811
+ r.should == "<textarea name=\"foo\"></textarea>"
812
+ end
813
+
814
+
815
+ # TODO: Why is this required?
816
+ # ---------------------------
817
+ #
818
+ # it "should handle a nil attributes hash" do
819
+ # text_area("CONTENT", nil).should == "<textarea>CONTENT</textarea>"
820
+ # end
821
+
822
+ it "should render a label when the label is passed in" do
823
+ result = @c.render :label
824
+ result.should match(/<label.*>LABEL<\/label><textarea/)
825
+ res = result.scan(/<[^>]*>/)
826
+ res[1].should_not match_tag(:textarea, :label => "LABEL")
827
+ end
828
+
829
+ it "should be disabled if :disabled => true is passed in" do
830
+ r = @c.render :disabled
831
+ r.should match_tag(:textarea, :disabled => "disabled")
832
+ end
833
+ end
834
+
835
+ describe "bound_text_area" do
836
+
837
+ before do
838
+ @c = BoundTextAreaSpecs.new(Merb::Request.new({}))
839
+ @obj = FakeModel.new
840
+ @c.instance_variable_set(:@obj, @obj)
841
+ end
842
+
843
+ it "should provide :id attribute" do
844
+ r = @c.render :basic
845
+ r.should match_tag(:textarea, :id => 'fake_model_foo', :name => "fake_model[foo]")
846
+ r.should =~ />\s*#{@obj.foo}\s*</
847
+ end
848
+ end
849
+
850
+ describe "select" do
851
+
852
+ before do
853
+ @c = SelectSpecs.new(Merb::Request.new({}))
854
+ end
855
+
856
+ it "should provide a blank option if you :include_blank" do
857
+ r = @c.render :blank
858
+ r.should =~ /<option.*>\s*<\/option>/
859
+ end
860
+
861
+ it "should render the select tag with suffix '[]' to name when :multiple => true" do
862
+ r = @c.render :multiple
863
+ r.should match_tag( :select, :name => "foo[]" )
864
+ end
865
+ end
866
+
867
+ describe "bound_select" do
868
+
869
+ before do
870
+ @c = BoundSelectSpecs.new(Merb::Request.new({}))
871
+ @c.instance_variable_set(:@obj, FakeModel.new)
872
+ end
873
+
874
+ it "should render the select tag with the correct id and name" do
875
+ r = @c.render :basic
876
+ r.should match_tag( :select, :id => "fake_model_foo", :name => "fake_model[foo]" )
877
+ end
878
+
879
+ it "should render the select tag with suffix '[]' to name when :multiple => true" do
880
+ r = @c.render :multiple
881
+ r.should match_tag( :select, :id => "fake_model_foo", :name => "fake_model[foo][]" )
882
+ end
883
+
884
+ it "should include a blank option" do
885
+ r = @c.render :blank
886
+ r.should match_tag(:option, :value => '')
887
+ r.should =~ /<option.*>\s*<\/option>/
888
+ end
889
+
890
+ it "should render a prompt option without a value" do
891
+ r = @c.render :prompt
892
+ r.should match_tag(:option, :value => '')
893
+ r.should =~ /<option.*>Choose<\/option>/
894
+ end
895
+
896
+ it "should render a select tag with options" do
897
+ r = @c.render :with_options
898
+ r.should match_tag( :select, :class => "class1 class2", :title=> "This is the title" )
899
+ r.should =~ /<select.*>\s*<\/select>/
900
+ end
901
+
902
+ it "should render a select tag with options and a blank option" do
903
+ r = @c.render :with_options_with_blank
904
+ r.should match_tag( :select, :title => "TITLE" )
905
+ r.should match_tag( :option, :value => '' )
906
+ r.should =~ /<option.*>\s*<\/option>/
907
+ end
908
+
909
+ # Not sure how this makes any sense
910
+ # ---------------------------------
911
+ #
912
+ # it "should render the text as the value if no text_method is specified" do
913
+ # form_for @obj do
914
+ # content = select( :foo, :collection => [FakeModel] )
915
+ # content.should match_tag( :option, :value => "FakeModel" )
916
+ # end
917
+ # end
918
+
919
+ end
920
+
921
+ describe "bound option tags" do
922
+
923
+ before do
924
+ @c = BoundOptionTagSpecs.new(Merb::Request.new({}))
925
+ @c.instance_variable_set(:@obj, FakeModel.new)
926
+ end
927
+
928
+
929
+ it "should use text_method and value_method for tag generation" do
930
+ r = @c.render :text_and_value
931
+ r.should match_tag( :option, :content => "foowee", :value => "7" )
932
+ r.should match_tag( :option, :content => "foowee2", :value => "barbar" )
933
+
934
+ # content = options_from_collection_for_select( [FakeModel.new, FakeModel2.new], :text_method => 'foo', :value_method => 'bar' )
935
+ # content.should match_tag( :option, :content => "foowee", :value => "7" )
936
+ # content.should match_tag( :option, :content => "foowee2", :value => "barbar" )
937
+ end
938
+
939
+ it "should render a hash of arrays as a grouped select box" do
940
+ model1 = FakeModel.new ; model1.make = "Ford" ; model1.model = "Mustang" ; model1.vin = '1'
941
+ model2 = FakeModel.new ; model2.make = "Ford" ; model2.model = "Falcon" ; model2.vin = '2'
942
+ model3 = FakeModel.new ; model3.make = "Holden" ; model3.model = "Commodore" ; model3.vin = '3'
943
+ @c.instance_variable_set(:@model1, model1)
944
+ @c.instance_variable_set(:@model2, model2)
945
+ @c.instance_variable_set(:@model3, model3)
946
+ @c.instance_variable_set(:@collection, [model1, model2, model3].inject({}) {|s,e| (s[e.make] ||= []) << e; s })
947
+ r = @c.render :grouped
948
+ # Blank actually defaults to ""
949
+ r.should =~ /<optgroup label=\"Ford\"><option/
950
+ r.should match_tag( :optgroup, :label => "Ford" )
951
+ r.should match_tag( :option, :selected => "selected", :value => "1", :content => "Mustang" )
952
+ r.should match_tag( :option, :value => "2", :content => "Falcon" )
953
+ r.should match_tag( :optgroup, :label => "Holden" )
954
+ r.should match_tag( :option, :value => "3", :content => "Commodore" )
955
+
956
+ # collection = [@model1, @model2, @model3].inject({}) {|s,e| (s[e.make] ||= []) << e; s }
957
+ # content = options_from_collection_for_select(collection, :text_method => 'model', :value_method => 'vin', :selected => '1')
958
+ end
959
+
960
+ it "should render a collection of nested value/content arrays" do
961
+ r = @c.render :nested
962
+ r.should match_tag(:select, :id => "fake_model_foo", :name => "fake_model[foo]")
963
+ r.should match_tag(:option, :value => "small", :content => "Small")
964
+ r.should match_tag(:option, :value => "medium", :content => "Medium")
965
+ r.should match_tag(:option, :value => "large", :content => "Large")
966
+ end
967
+
968
+ # Is this really worth the extra speed hit? I'm thinking not
969
+ # ----------------------------------------------------------
970
+ #
971
+ # it "should humanize and titlize keys in the label for the option group" do
972
+ # collection = { :some_snake_case_key => [FakeModel.new] }
973
+ # form_for @obj do
974
+ # content = select( :foo, :collection => collection )
975
+ # content.should match_tag( :optgroup, :label => "Some Snake Case Key" )
976
+ # end
977
+ # end
978
+
979
+ end
980
+
981
+ require "hpricot"
982
+
983
+ describe "option tags" do
984
+
985
+ before do
986
+ @c = OptionTagSpecs.new(Merb::Request.new({}))
987
+ @c.instance_variable_set(:@collection, [['rabbit','Rabbit'],['horse','Horse'],['bird','Bird']])
988
+ end
989
+
990
+ it "should provide an option tag for each item in the collection" do
991
+ r = @c.render :collection
992
+ doc = Hpricot( r )
993
+ (doc/"option").size.should == 3
994
+ end
995
+
996
+ it "should provide a blank option" do
997
+ r = @c.render :with_blank
998
+ r.should match_tag( :option, :value => '' )
999
+ end
1000
+
1001
+ it "should render the prompt option at the top" do
1002
+ r = @c.render :with_prompt
1003
+ #ontent = select( :collection => [["foo", "Foo"]], :prompt => 'Choose' )
1004
+ r.should match(/<option[^>]*>Choose<\/option>[^<]*<option[^>]*>Foo<\/option>/)
1005
+ end
1006
+
1007
+ it "should provide selected options by value" do
1008
+ r = @c.render :selected
1009
+ r.should match_tag( :option, :value => 'rabbit', :selected => 'selected', :content => 'Rabbit' )
1010
+ r.should_not match_tag( :option, :value => 'chicken', :selected => nil, :content => 'Chicken' )
1011
+ end
1012
+
1013
+ it "should handle arrays for selected when :multiple is true" do
1014
+ r = @c.render :multiple_selects
1015
+ r.should match_tag( :option, :value => 'minutes', :selected => 'selected', :content => 'Time' )
1016
+ r.should match_tag( :option, :value => 'dollars', :selected => 'selected', :content => 'Money' )
1017
+ end
1018
+
1019
+ it "should render a hash of options as optgroup" do
1020
+ r = @c.render :optgroups
1021
+ r.should match_tag( :optgroup, :label => 'Fruit' )
1022
+ r.should match_tag( :optgroup, :label => 'Vegetables' )
1023
+ r.should match_tag( :option, :value => 'banana', :selected => 'selected', :content => 'Banana' )
1024
+ end
1025
+
1026
+ it "should accept an array of strings in :collection as the content/value of each option" do
1027
+ r = @c.render :array
1028
+ r.should match_tag(:option, :content => "one", :value => "one")
1029
+ r.should match_tag(:option, :content => "two", :value => "two")
1030
+ end
1031
+
1032
+ it "should only pass :selected and :value attrs to <option> tags" do
1033
+ r = @c.render :no_extra_attributes
1034
+ r = r.slice(/<option[^>]*>[^<]*<\/option>/)
1035
+ r.should match_tag(:option, :value => "rabbit", :content => "Rabbit")
1036
+ r.should_not match_tag(:option, :id => "my_id", :name => "my_name", :class => "classy")
1037
+ end
1038
+
1039
+ it "should not pollute the <select> attributes with <option> attributes" do
1040
+ r = @c.render :clean
1041
+ r = r.slice(/<select[^>]*>/)
1042
+ r.should_not match_tag(:select, :value => "banana", :selected => "selected")
1043
+ end
1044
+ end
1045
+
1046
+ describe "fieldset" do
1047
+
1048
+ before :each do
1049
+ @c = FieldsetSpecs.new(Merb::Request.new({}))
1050
+ end
1051
+
1052
+ it "should provide legend option" do
1053
+ r = @c.render :legend
1054
+ # res = fieldset :legend => 'TEST' do
1055
+ # _buffer << "CONTENT"
1056
+ # end
1057
+ r.should include("CONTENT")
1058
+ r.should match_tag(:fieldset, {})
1059
+ r.should match_tag(:legend, :content => 'TEST')
1060
+ end
1061
+
1062
+ end
1063
+
1064
+ describe "label" do
1065
+
1066
+ before :each do
1067
+ @c = LabelSpecs.new(Merb::Request.new({}))
1068
+ end
1069
+
1070
+ it "should render a label tag" do
1071
+ r = @c.render :basic
1072
+ #r = label("First Name", :id => "user_first_name")
1073
+ r.should match_tag(:label, :for => "user_first_name", :content => "First Name")
1074
+ end
1075
+ end
1076
+
1077
+ describe "file_field" do
1078
+
1079
+ before :each do
1080
+ @c = FileFieldSpecs.new(Merb::Request.new({}))
1081
+ end
1082
+
1083
+ it "should return a basic file field based on the values passed in" do
1084
+ r = @c.render :with_values
1085
+ #file_field(:name => "foo", :value => "bar")
1086
+ r.should match_tag( :input, :type => "file", :name => "foo", :value => "bar")
1087
+ end
1088
+
1089
+ it "should wrap the field in a label if the :label option is passed to the file" do
1090
+ r = @c.render :with_label
1091
+ r.should match(/<label>LABEL<\/label><input type="file" class="file"\s*\/>/)
1092
+ end
1093
+
1094
+ it "should be disabled if :disabled => true is passed in" do
1095
+ r = @c.render :disabled
1096
+ r.should match_tag(:input, :type => "file", :disabled => "disabled")
1097
+ end
1098
+
1099
+ it "should make the surrounding form multipart" do
1100
+ r = @c.render :makes_multipart
1101
+ r.should match_tag(:form, :enctype => "multipart/form-data")
1102
+ end
1103
+ end
1104
+
1105
+ describe "bound_file_field" do
1106
+
1107
+ before :each do
1108
+ @c = BoundFileFieldSpecs.new(Merb::Request.new({}))
1109
+ @c.instance_variable_set(:@obj, FakeModel.new)
1110
+ end
1111
+
1112
+ it "should take a string object and return a useful file control" do
1113
+ r = @c.render :takes_string
1114
+ r.should match_tag(:input, :type => "file", :name => "fake_model[foo]", :value => "foowee")
1115
+ end
1116
+
1117
+ it "should take additional attributes and use them" do
1118
+ r = @c.render :additional_attributes
1119
+ r.should match_tag(:input, :type => "file", :name => "fake_model[foo]", :value => "foowee", :bar => "7")
1120
+ end
1121
+
1122
+ it "should wrap the file_field in a label if the :label option is passed in" do
1123
+ r = @c.render :with_label
1124
+ # form = form_for @obj do
1125
+ # _buffer << text_field(:foo, :label => "LABEL")
1126
+ # end
1127
+ r.should match(/<label.*>LABEL<\/label><input/)
1128
+ res = r.scan(/<[^>]*>/)
1129
+ res[2].should_not match_tag(:input, :label => "LABEL")
1130
+ end
1131
+ end
1132
+
1133
+ describe "submit" do
1134
+
1135
+ before :each do
1136
+ @c = SubmitSpecs.new(Merb::Request.new({}))
1137
+ end
1138
+
1139
+ it "should return a basic submit input based on the values passed in" do
1140
+ r = @c.render :submit_with_values
1141
+ r.should match_tag(:input, :type => "submit", :name => "foo", :value => "Done")
1142
+ end
1143
+
1144
+ it "should provide an additional label tag if the :label option is passed in" do
1145
+ r = @c.render :submit_with_label
1146
+ r.should match(/<input.*type="submit"/)
1147
+ r.should match(/<input.*name="submit"/)
1148
+ r.should match(/<input.*value="Done"/)
1149
+ r.should match(/<label.*>LABEL<\/label>/)
1150
+ end
1151
+
1152
+ it "should be disabled if :disabled => true is passed in" do
1153
+ r = @c.render :disabled_submit
1154
+ r.should match_tag(:input, :type => "submit", :value => "Done", :disabled => "disabled")
1155
+ end
1156
+ end
1157
+
1158
+ describe "button" do
1159
+
1160
+ before :each do
1161
+ @c = ButtonSpecs.new(Merb::Request.new({}))
1162
+ end
1163
+
1164
+ it "should return a button based on the values passed in" do
1165
+ r = @c.render :button_with_values
1166
+ r.should match_tag(:button, :type => "button", :name => "foo", :value => "bar", :content => "Click Me")
1167
+ end
1168
+
1169
+ it "should provide an additional label tag if the :label option is passed in" do
1170
+ r = @c.render :button_with_label
1171
+ r.should match(/<button.*value="foo"/)
1172
+ r.should match(/<label.*>LABEL<\/label>/)
1173
+ end
1174
+
1175
+ it "should be disabled if :disabled => true is passed in" do
1176
+ r = @c.render :disabled_button
1177
+ r.should match_tag(:button, :disabled => "true")
1178
+ end
1179
+ end
1180
+
1181
+
1182
+ class MyBuilder < Merb::Helpers::Form::Builder::Base
1183
+
1184
+ def update_bound_controls(method, attrs, type)
1185
+ super
1186
+ attrs[:bound] = type
1187
+ end
1188
+
1189
+ def update_unbound_controls(attrs, type)
1190
+ super
1191
+ attrs[:unbound] = type
1192
+ end
1193
+
1194
+ end
1195
+
1196
+ describe "custom builder" do
1197
+
1198
+ before :each do
1199
+ @c = CustomBuilderSpecs.new(Merb::Request.new({}))
1200
+ @c.instance_variable_set(:@obj, FakeModel.new)
1201
+ end
1202
+
1203
+ it "should let you override update_bound_controls" do
1204
+ r = @c.render :everything
1205
+ r.should =~ / bound="file"/
1206
+ r.should =~ / bound="text"/
1207
+ r.should =~ / bound="hidden"/
1208
+ r.should =~ / bound="password"/
1209
+ r.should =~ / bound="radio"/
1210
+ r.should =~ / bound="text_area"/
1211
+ end
1212
+
1213
+ it "should let you override update_unbound_controls" do
1214
+ r = @c.render :everything
1215
+ r.should match_tag(:button, :unbound => "button")
1216
+ r.should match_tag(:input, :unbound => "submit")
1217
+ r.should match_tag(:textarea, :unbound => "text_area")
1218
+ end
1219
+ end
1220
+
1221
+
1222
+ describe 'delete_button' do
1223
+
1224
+ before :each do
1225
+ @controller = DeleteButtonSpecs.new(Merb::Request.new({}))
1226
+ @controller.instance_variable_set(:@obj, FakeModel.new)
1227
+ end
1228
+
1229
+ it "should have a default submit button text" do
1230
+ result = @controller.render :simple_delete # <%= delete_button @obj %>
1231
+ result.should match(/<input type=\"submit\">Delete<\/input>/)
1232
+ end
1233
+
1234
+ it 'should return a button inside of a form for the object' do
1235
+ result = @controller.render :simple_delete # <%= delete_button @obj %>
1236
+ result.should match_tag(:form, :action => "/fake_models/fake_model", :method => "post")
1237
+ result.should match_tag(:input, :type => "hidden", :value => "DELETE", :name => "_method")
1238
+ end
1239
+
1240
+ it 'should allow you to modify the label' do
1241
+ result = @controller.render :delete_with_label # <%= delete_button(@obj, "Delete moi!") %>
1242
+ result.should match(/<input type=\"submit\">Delete moi!<\/input>/)
1243
+ end
1244
+
1245
+ it "should allow you to pass some extra params like a class" do
1246
+ result = @controller.render :delete_with_extra_params
1247
+ result.should match(/<input type=\"submit\" class=\"custom-class\">Delete<\/input>/)
1248
+ end
1249
+
1250
+ it "should allow to pass an explicit url as a string" do
1251
+ result = @controller.render :delete_with_explicit_url # <%= delete_button('/test/custom_url') %>
1252
+ result.should match_tag(:form, :action => "/test/custom_url", :method => "post")
1253
+ end
1254
+
1255
+ end
1256
+
1257
+ # describe "control_value" do
1258
+ #
1259
+ #
1260
+ # it 'should escape [&"<>]' do
1261
+ # @obj.vin = '&"<>'
1262
+ # f = form_for :obj do
1263
+ # control_value(:vin).should == '&amp;&quot;&lt;&gt;'
1264
+ # end
1265
+ # end
1266
+ # end