merb 0.4.0 → 0.4.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 (143) hide show
  1. data/README +23 -160
  2. data/Rakefile +15 -14
  3. data/app_generators/merb/merb_generator.rb +4 -3
  4. data/app_generators/merb/templates/Rakefile +1 -6
  5. data/app_generators/merb/templates/app/mailers/views/layout/{application.erb → application.html.erb} +0 -0
  6. data/app_generators/merb/templates/app/mailers/views/layout/application.text.erb +1 -0
  7. data/app_generators/merb/templates/app/parts/views/layout/application.html.erb +1 -0
  8. data/app_generators/merb/templates/app/views/layout/application.html.erb +2 -2
  9. data/app_generators/merb/templates/config/dependencies.rb +1 -1
  10. data/app_generators/merb/templates/config/router.rb +4 -1
  11. data/app_generators/merb/templates/spec/spec_helper.rb +2 -3
  12. data/lib/autotest/merb_rspec.rb +1 -0
  13. data/lib/merb/abstract_controller.rb +31 -2
  14. data/lib/merb/controller.rb +5 -5
  15. data/lib/merb/core_ext/get_args.rb +5 -1
  16. data/lib/merb/exceptions.rb +17 -0
  17. data/lib/merb/generators/merb_app/merb_app.rb +4 -1
  18. data/lib/merb/generators/merb_plugin.rb +4 -1
  19. data/lib/merb/logger.rb +5 -1
  20. data/lib/merb/mail_controller.rb +1 -1
  21. data/lib/merb/mailer.rb +2 -2
  22. data/lib/merb/mixins/controller.rb +5 -1
  23. data/lib/merb/mixins/render.rb +57 -27
  24. data/lib/merb/part_controller.rb +1 -1
  25. data/lib/merb/request.rb +2 -2
  26. data/lib/merb/server.rb +33 -5
  27. data/lib/merb/template/erubis.rb +1 -1
  28. data/lib/merb.rb +15 -5
  29. data/merb_generators/resource/resource_generator.rb +9 -2
  30. data/spec/fixtures/config/merb.yml +18 -0
  31. data/spec/fixtures/controllers/dispatch_spec_controllers.rb +227 -0
  32. data/spec/fixtures/controllers/render_spec_controllers.rb +115 -0
  33. data/spec/fixtures/foo.rb +3 -0
  34. data/spec/fixtures/mailers/views/layout/application.html.erb +3 -0
  35. data/spec/fixtures/mailers/views/layout/application.text.erb +3 -0
  36. data/spec/fixtures/mailers/views/test_mail_controller/eighth.html.erb +1 -0
  37. data/spec/fixtures/mailers/views/test_mail_controller/eighth.text.erb +1 -0
  38. data/spec/fixtures/mailers/views/test_mail_controller/first.html.erb +1 -0
  39. data/spec/fixtures/mailers/views/test_mail_controller/first.text.erb +1 -0
  40. data/spec/fixtures/mailers/views/test_mail_controller/ninth.html.erb +1 -0
  41. data/spec/fixtures/mailers/views/test_mail_controller/ninth.text.erb +1 -0
  42. data/spec/fixtures/mailers/views/test_mail_controller/second.text.erb +1 -0
  43. data/spec/fixtures/mailers/views/test_mail_controller/third.html.erb +1 -0
  44. data/spec/fixtures/models/router_spec_models.rb +20 -0
  45. data/spec/fixtures/parts/views/layout/todo_part.html.erb +3 -0
  46. data/spec/fixtures/parts/views/layout/todo_part.xml.erb +3 -0
  47. data/spec/fixtures/parts/views/todo_part/formatted_output.html.erb +1 -0
  48. data/spec/fixtures/parts/views/todo_part/formatted_output.js.erb +1 -0
  49. data/spec/fixtures/parts/views/todo_part/formatted_output.xml.erb +1 -0
  50. data/spec/fixtures/parts/views/todo_part/list.html.erb +3 -0
  51. data/spec/fixtures/sample.txt +1 -0
  52. data/spec/fixtures/views/erubis.html.erb +1 -0
  53. data/spec/fixtures/views/examples/_erubis.html.erb +1 -0
  54. data/spec/fixtures/views/examples/_haml.html.haml +1 -0
  55. data/spec/fixtures/views/examples/_markaby.html.mab +1 -0
  56. data/spec/fixtures/views/examples/_throw_content.html.erb +6 -0
  57. data/spec/fixtures/views/examples/hello.xml.builder +1 -0
  58. data/spec/fixtures/views/examples/js.js.erb +1 -0
  59. data/spec/fixtures/views/examples/template_catch_content.html.erb +15 -0
  60. data/spec/fixtures/views/examples/template_catch_content_from_partial.html.erb +6 -0
  61. data/spec/fixtures/views/examples/template_throw_content.html.erb +10 -0
  62. data/spec/fixtures/views/exceptions/admin_access_required.html.erb +1 -0
  63. data/spec/fixtures/views/extension_template_controller/_nested_js.js.erb +1 -0
  64. data/spec/fixtures/views/extension_template_controller/_nested_xml.xml.erb +1 -0
  65. data/spec/fixtures/views/extension_template_controller/_render_partial_multiple_times.html.erb +1 -0
  66. data/spec/fixtures/views/extension_template_controller/erubis_templates.html.erb +1 -0
  67. data/spec/fixtures/views/extension_template_controller/erubis_templates.js.erb +1 -0
  68. data/spec/fixtures/views/extension_template_controller/erubis_templates.rhtml +1 -0
  69. data/spec/fixtures/views/extension_template_controller/erubis_templates.xml.erb +1 -0
  70. data/spec/fixtures/views/extension_template_controller/haml_index.html.haml +0 -0
  71. data/spec/fixtures/views/extension_template_controller/haml_templates.html.haml +1 -0
  72. data/spec/fixtures/views/extension_template_controller/haml_templates.js.haml +1 -0
  73. data/spec/fixtures/views/extension_template_controller/haml_templates.xml.haml +1 -0
  74. data/spec/fixtures/views/extension_template_controller/index.html.erb +0 -0
  75. data/spec/fixtures/views/extension_template_controller/markaby_index.html.mab +0 -0
  76. data/spec/fixtures/views/extension_template_controller/markaby_templates.html.mab +1 -0
  77. data/spec/fixtures/views/extension_template_controller/markaby_templates.js.mab +1 -0
  78. data/spec/fixtures/views/extension_template_controller/markaby_templates.xml.mab +1 -0
  79. data/spec/fixtures/views/extension_template_controller/render_multiple_partials.html.erb +4 -0
  80. data/spec/fixtures/views/extension_template_controller/render_nested_js.js.erb +1 -0
  81. data/spec/fixtures/views/extension_template_controller/render_nested_xml.xml.erb +1 -0
  82. data/spec/fixtures/views/haml.html.haml +1 -0
  83. data/spec/fixtures/views/haml.xml.haml +2 -0
  84. data/spec/fixtures/views/layout/application.html.erb +1 -0
  85. data/spec/fixtures/views/layout/application.xml.erb +1 -0
  86. data/spec/fixtures/views/layout/nested/example.html.erb +1 -0
  87. data/spec/fixtures/views/markaby.html.mab +1 -0
  88. data/spec/fixtures/views/nested/example/test.html.erb +1 -0
  89. data/spec/fixtures/views/partials/_erubis.html.erb +1 -0
  90. data/spec/fixtures/views/partials/_erubis_collection.html.erb +1 -0
  91. data/spec/fixtures/views/partials/_erubis_collection_with_locals.html.erb +1 -0
  92. data/spec/fixtures/views/partials/_erubis_new.html.erb +1 -0
  93. data/spec/fixtures/views/partials/_haml.html.haml +1 -0
  94. data/spec/fixtures/views/partials/_haml_collection.html.haml +1 -0
  95. data/spec/fixtures/views/partials/_haml_collection_with_locals.html.haml +1 -0
  96. data/spec/fixtures/views/partials/_haml_new.html.haml +1 -0
  97. data/spec/fixtures/views/partials/_markaby.html.mab +1 -0
  98. data/spec/fixtures/views/partials/_markaby_collection.html.mab +1 -0
  99. data/spec/fixtures/views/partials/_markaby_collection_with_locals.html.mab +1 -0
  100. data/spec/fixtures/views/partials/_markaby_new.html.mab +1 -0
  101. data/spec/fixtures/views/render_object_controller/render_object_with_template.html.erb +1 -0
  102. data/spec/fixtures/views/render_object_controller/render_object_with_template.js.erb +1 -0
  103. data/spec/fixtures/views/render_object_controller/render_object_with_template.xml.erb +1 -0
  104. data/spec/fixtures/views/template_views/interface__buffer_erubis.html.erb +4 -0
  105. data/spec/fixtures/views/template_views/interface__buffer_haml.html.haml +7 -0
  106. data/spec/fixtures/views/template_views/interface__buffer_markaby.html.mab +7 -0
  107. data/spec/fixtures/views/template_views/interface_capture_erubis.html.erb +15 -0
  108. data/spec/fixtures/views/template_views/interface_capture_haml.html.haml +15 -0
  109. data/spec/fixtures/views/template_views/interface_capture_markaby.html.mab +4 -0
  110. data/spec/fixtures/views/template_views/interface_concat_erubis.html.erb +12 -0
  111. data/spec/fixtures/views/template_views/interface_concat_haml.html.haml +11 -0
  112. data/spec/fixtures/views/template_views/interface_concat_markaby.html.mab +14 -0
  113. data/spec/fixtures/views/test.dir/the_template.html.erb +1 -0
  114. data/spec/merb/abstract_controller_spec.rb +37 -0
  115. data/spec/merb/caching_spec.rb +102 -0
  116. data/spec/merb/config_spec.rb +29 -0
  117. data/spec/merb/controller_filters_spec.rb +188 -0
  118. data/spec/merb/controller_spec.rb +144 -0
  119. data/spec/merb/cookie_store_spec.rb +85 -0
  120. data/spec/merb/core_ext_spec.rb +430 -0
  121. data/spec/merb/dispatch_spec.rb +514 -0
  122. data/spec/merb/fake_request_spec.rb +72 -0
  123. data/spec/merb/form_control_mixin_spec.rb +431 -0
  124. data/spec/merb/generator_spec.rb +121 -0
  125. data/spec/merb/handler_spec.rb +169 -0
  126. data/spec/merb/mail_controller_spec.rb +144 -0
  127. data/spec/merb/mailer_spec.rb +87 -0
  128. data/spec/merb/multipart_spec.rb +49 -0
  129. data/spec/merb/part_controller_spec.rb +92 -0
  130. data/spec/merb/plugins_spec.rb +80 -0
  131. data/spec/merb/render_spec.rb +378 -0
  132. data/spec/merb/request_spec.rb +243 -0
  133. data/spec/merb/responder_spec.rb +561 -0
  134. data/spec/merb/router_spec.rb +726 -0
  135. data/spec/merb/template_spec.rb +41 -0
  136. data/spec/merb/upload_handler_spec.rb +101 -0
  137. data/spec/merb/view_context_spec.rb +148 -0
  138. data/spec/spec_generator_helper.rb +19 -0
  139. data/spec/spec_helper.rb +88 -0
  140. metadata +203 -65
  141. data/lib/merb/caching/store/memcache.rb +0 -20
  142. data/script/destroy +0 -14
  143. data/script/generate +0 -14
@@ -0,0 +1,430 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe "A Numeric object" do
4
+
5
+ it "should be able to convert to US currency" do
6
+ 1.5.to_currency.should == "$1.50"
7
+ end
8
+
9
+ it "should be able to convert to Danish currency" do
10
+ 15_000_000.5.to_currency(nil, ".", ",", "DM").should == "15.000.000,50DM"
11
+ end
12
+
13
+ {
14
+ :microsecond => Float(10 ** -6), :millisecond => Float(10 ** -3), :second => 1,
15
+ :minute => 60, :hour => 3600, :day => 86400, :week => 604800,
16
+ :month => 2592000, :year => 31536000, :decade => 315360000
17
+ }.each do |method,seconds|
18
+
19
+ it "should be able to convert to #{method}s (singular version)" do
20
+ 1.send(method).should == seconds
21
+ end
22
+
23
+ it "should be able to convert to #{method}s (plural version)" do
24
+ 2.send("#{method}s").should == seconds * 2
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ class MyString < String; end
32
+ class String
33
+ def self.define_meta meth, val
34
+ meta_def meth do; val; end
35
+ end
36
+ end
37
+
38
+ describe "An object" do
39
+
40
+ it "should be able to return a passed in object that is modified by a block" do
41
+ (returning({}) {|x| x.merge!(:foo => :bar)}).should == {:foo => :bar}
42
+ end
43
+
44
+ it "should be able to get a meta class" do
45
+ MyString.meta_class.to_s.should == "#<Class:MyString>"
46
+ end
47
+
48
+ it "should be able to execute code in the meta-class' context" do
49
+ (MyString.meta_eval { self }).should == MyString.meta_class
50
+ end
51
+
52
+ it "should be able to define a method on the meta-class" do
53
+ MyString.define_meta :foo, :bar
54
+ MyString.foo.should == :bar
55
+ end
56
+
57
+ it "should be able to define methods on its instances" do
58
+ MyString.class_def :foo do; :bar; end
59
+ MyString.new.foo.should == :bar
60
+ end
61
+
62
+ {[] => true,
63
+ [1] => false,
64
+ [nil] => false,
65
+ nil => true,
66
+ true => false,
67
+ false => true,
68
+ "" => true,
69
+ " " => true,
70
+ " hey " => false
71
+ }.each do |obj, expected|
72
+ it "should be able to determine whether the #{obj.class} #{obj.inspect} is blank" do
73
+ obj.blank?.should == expected
74
+ end
75
+ end
76
+ end
77
+
78
+ describe Enumerable do
79
+
80
+ before do
81
+ @mascots = ['louie', 'bert', 'ernie']
82
+ end
83
+
84
+ it "should perform injecting" do
85
+ @mascots.injecting({}){|m,i| m[i] = i.size }.should ==
86
+ {'louie'=>5, 'bert'=>4, 'ernie'=>5}
87
+ end
88
+
89
+ it "should find arrays of things inside other arrays" do
90
+ @mascots.include_any?('louie', 'sasquatch').should be_true
91
+ end
92
+
93
+ it "should recognize absence of arrays of things inside other arrays" do
94
+ @mascots.include_any?('chicken', 'sasquatch').should be_false
95
+ end
96
+
97
+ it "should group by" do
98
+ groups = (1..6).group_by{|i| i%3}
99
+ groups[0].should == [3,6]
100
+ groups[1].should == [1,4]
101
+ groups[2].should == [2,5]
102
+ end
103
+
104
+ end
105
+
106
+ describe Symbol do
107
+
108
+ it "should be able to call Symbol#to_proc" do
109
+ ['foo', 'bar'].map(&:reverse).should == ['oof', 'rab']
110
+ end
111
+
112
+ end
113
+
114
+ # Class cattr_reader
115
+
116
+ class ClassWithCAttrReader
117
+ cattr_reader :bacon
118
+ def initialize; @@bacon = "chunky"; end
119
+ end
120
+
121
+ describe "Core Class with cattr_reader", :shared => true do
122
+
123
+ it "should read value from attribute" do
124
+ @klass.bacon.should == "chunky"
125
+ end
126
+
127
+ it "should not write to attribute" do
128
+ lambda {
129
+ @klass.bacon = "soggy"
130
+ }.should raise_error(NoMethodError)
131
+ end
132
+
133
+ end
134
+
135
+ describe Class, "with cattr_reader" do
136
+
137
+ before do
138
+ @klass = ClassWithCAttrReader.new.class
139
+ end
140
+ it_should_behave_like "Core Class with cattr_reader"
141
+
142
+ end
143
+
144
+ describe Class, "with cattr_reader (instantiated)" do
145
+
146
+ before do
147
+ @klass = ClassWithCAttrReader.new
148
+ end
149
+ it_should_behave_like "Core Class with cattr_reader"
150
+
151
+ end
152
+
153
+ # Class cattr_writer
154
+
155
+ class ClassWithCAttrWriter
156
+ cattr_writer :bacon
157
+ def self.chunky?; @@bacon == "chunky"; end
158
+ def chunky?; self.class.chunky?; end
159
+ end
160
+
161
+ describe "Core Class with cattr_writer", :shared => true do
162
+
163
+ it "should write value to attribute" do
164
+ @klass.should be_chunky
165
+ end
166
+
167
+ it "should not read attribute" do
168
+ lambda {
169
+ @klass.bacon
170
+ }.should raise_error(NoMethodError)
171
+ end
172
+
173
+ end
174
+
175
+ describe Class, "with cattr_writer" do
176
+
177
+ before do
178
+ @klass = ClassWithCAttrWriter.new.class
179
+ @klass.bacon = "chunky"
180
+ end
181
+ it_should_behave_like "Core Class with cattr_writer"
182
+
183
+ end
184
+
185
+ describe Class, "with cattr_writer (instantiated)" do
186
+
187
+ before do
188
+ @klass = ClassWithCAttrWriter.new
189
+ @klass.bacon = "chunky"
190
+ end
191
+ it_should_behave_like "Core Class with cattr_writer"
192
+
193
+ end
194
+
195
+ describe Hash, "environmentize_keys!" do
196
+ it "should transform keys to uppercase text" do
197
+ { :test_1 => 'test', 'test_2' => 'test', 1 => 'test'}.environmentize_keys!.should ==
198
+ { 'TEST_1' => 'test', 'TEST_2' => 'test', '1' => 'test'}
199
+ end
200
+
201
+ it "should only transform one level of keys" do
202
+ { :test_1 => { :test2 => 'test'}}.environmentize_keys!.should ==
203
+ { 'TEST_1' => { :test2 => 'test'}}
204
+ end
205
+ end
206
+
207
+ describe Hash, "to_xml_attributes" do
208
+
209
+ before do
210
+ @hash = { :one => "ONE", "two" => "TWO" }
211
+ end
212
+
213
+ it "should turn the hash into xml attributes" do
214
+ attrs = @hash.to_xml_attributes
215
+ attrs.should match( /one="ONE"/m )
216
+ attrs.should match( /two="TWO"/m )
217
+ end
218
+
219
+ end
220
+
221
+ describe Hash, "from_xml" do
222
+
223
+ it "should transform a simple tag with content" do
224
+ xml = "<tag>This is the contents</tag>"
225
+ Hash.from_xml( xml ).should == { 'tag' => 'This is the contents' }
226
+ end
227
+
228
+ it "should transform a simple tag with attributes" do
229
+ xml = "<tag attr1='1' attr2='2'></tag>"
230
+ Hash.from_xml( xml ).should == { 'tag' => {
231
+ 'attr1' => '1',
232
+ 'attr2' => '2'
233
+ }}
234
+ end
235
+
236
+ it "should transform repeating siblings into an array" do
237
+ xml =<<-XML
238
+ <opt>
239
+ <user login="grep" fullname="Gary R Epstein" />
240
+ <user login="stty" fullname="Simon T Tyson" />
241
+ </opt>
242
+ XML
243
+
244
+ Hash.from_xml( xml )['opt']['user'].should be_an_instance_of( Array )
245
+
246
+ Hash.from_xml( xml ).should =={ 'opt' => {'user' => [{
247
+ 'login' => 'grep',
248
+ 'fullname' => 'Gary R Epstein'
249
+ },{
250
+ 'login' => 'stty',
251
+ 'fullname' => 'Simon T Tyson'
252
+ }]
253
+ }}
254
+
255
+ end
256
+
257
+ it "should not transform non-repeating siblings into an array" do
258
+ xml =<<-XML
259
+ <opt>
260
+ <user login="grep" fullname="Gary R Epstein" />
261
+ </opt>
262
+ XML
263
+
264
+ Hash.from_xml( xml )['opt']['user'].should be_an_instance_of( Hash )
265
+
266
+ Hash.from_xml( xml ).should == { 'opt' => {
267
+ 'user' => {
268
+ 'login' => 'grep',
269
+ 'fullname' => 'Gary R Epstein'
270
+ }
271
+ }}
272
+ end
273
+
274
+ it "should typecast an integer" do
275
+ xml = "<tag type='integer'>10</tag>"
276
+ Hash.from_xml(xml)['tag'].should == 10
277
+ end
278
+
279
+ it "should typecast a true boolean" do
280
+ xml = "<tag type='boolean'>true</tag>"
281
+ Hash.from_xml( xml )['tag'].should be_true
282
+ end
283
+
284
+ it "should typecast a false boolean" do
285
+ ["false", "1", "0", "some word" ].each do |w|
286
+ Hash.from_xml( "<tag type='boolean'>#{w}</tag>" )['tag'].should be_false
287
+ end
288
+ end
289
+
290
+ it "should typecast a datetime" do
291
+ xml = "<tag type='datetime'>2007-12-31 10:32</tag>"
292
+ Hash.from_xml( xml )['tag'].should == Time.parse( '2007-12-31 10:32' ).utc
293
+ end
294
+
295
+ it "should typecast a date" do
296
+ xml = "<tag type='date'>2007-12-31</tag>"
297
+ Hash.from_xml( xml )['tag'].should == Date.parse( '2007-12-31' )
298
+ end
299
+
300
+ it "should unescape html entities" do
301
+ values = {
302
+ "<" => "&lt;",
303
+ ">" => "&gt;",
304
+ '"' => "&quot;",
305
+ "'" => "&apos;",
306
+ "&" => "&amp;"
307
+ }
308
+ values.each do |k,v|
309
+ xml = "<tag>Some content #{v}</tag>"
310
+ Hash.from_xml( xml )['tag'].should match( Regexp.new( k ) )
311
+ end
312
+ end
313
+
314
+ it "should undasherize keys as tags" do
315
+ xml = "<tag-1>Stuff</tag-1>"
316
+ Hash.from_xml( xml ).keys.should include( 'tag_1' )
317
+ end
318
+
319
+ it "should undasherize keys as attributes" do
320
+ xml = "<tag1 attr-1='1'></tag1>"
321
+ Hash.from_xml( xml )['tag1'].keys.should include( 'attr_1')
322
+ end
323
+
324
+ it "should undasherize keys as tags and attributes" do
325
+ xml = "<tag-1 attr-1='1'></tag-1>"
326
+ Hash.from_xml( xml ).keys.should include( 'tag_1' )
327
+ Hash.from_xml( xml )['tag_1'].keys.should include( 'attr_1')
328
+ end
329
+
330
+ it "should render nested content correctly" do
331
+ xml = "<root><tag1>Tag1 Content <em><strong>This is strong</strong></em></tag1></root>"
332
+ Hash.from_xml( xml )['root']['tag1'].should == "Tag1 Content <em><strong>This is strong</strong></em>"
333
+ end
334
+
335
+ it "should render nested content with split text nodes correctly" do
336
+ xml = "<root>Tag1 Content<em>Stuff</em> Hi There</root>"
337
+ Hash.from_xml( xml )['root'].should == "Tag1 Content<em>Stuff</em> Hi There"
338
+ end
339
+
340
+ it "should ignore attributes when a child is a text node" do
341
+ xml = "<root attr1='1'>Stuff</root>"
342
+ Hash.from_xml( xml ).should == { "root" => "Stuff" }
343
+ end
344
+
345
+ it "should ignore attributes when any child is a text node" do
346
+ xml = "<root attr1='1'>Stuff <em>in italics</em></root>"
347
+ Hash.from_xml( xml ).should == { "root" => "Stuff <em>in italics</em>" }
348
+ end
349
+
350
+ it "should correctly transform multiple children" do
351
+ xml = <<-XML
352
+ <user gender='m'>
353
+ <age type='integer'>35</age>
354
+ <name>Home Simpson</name>
355
+ <dob type='date'>1988-01-01</dob>
356
+ <joined-at type='datetime'>2000-04-28 23:01</joined-at>
357
+ <is-cool type='boolean'>true</is-cool>
358
+ </user>
359
+ XML
360
+ Hash.from_xml( xml ).should == { "user" =>
361
+ { "gender" => "m",
362
+ "age" => 35,
363
+ "name" => "Home Simpson",
364
+ "dob" => Date.parse( '1988-01-01' ),
365
+ "joined_at" => Time.parse( "2000-04-28 23:01"),
366
+ "is_cool" => true
367
+ }
368
+ }
369
+ end
370
+
371
+
372
+
373
+ end
374
+
375
+ class ClassWithAttrInitialize
376
+ attr_initialize :dog, :muppet
377
+ attr_accessor :dog, :muppet
378
+ end
379
+
380
+ describe ClassWithAttrInitialize do
381
+
382
+ it "should initialize with values" do
383
+ c = ClassWithAttrInitialize.new("louie", "bert")
384
+ c.dog.should == "louie"
385
+ c.muppet.should == "bert"
386
+ end
387
+
388
+ end
389
+
390
+ describe "A String" do
391
+ it "should convert a path/like/this to a Constant::String::Like::This" do
392
+ "path/like/this".to_const_string.should == "Path::Like::This"
393
+ "path".to_const_string.should == "Path"
394
+ "snake_case/path/with_several_parts".to_const_string.should == "SnakeCase::Path::WithSeveralParts"
395
+ end
396
+
397
+ it "should raise an error rather than freeze when trying to convert bad Paths/12Like/-this" do
398
+ Timeout::timeout(1) do
399
+ lambda do
400
+ "Paths/12Like/-this".to_const_string
401
+ end.should raise_error(String::InvalidPathConversion)
402
+ end.should_not raise_error(Timeout::Error)
403
+ end
404
+ end
405
+
406
+ describe "extracting options form argruments" do
407
+
408
+ def the_method(*args)
409
+ [extract_options_from_args!(args),args]
410
+ end
411
+
412
+ it "should extract the hash if the last item is a hash" do
413
+ opts,args = the_method(:one, :two, :key => :value)
414
+ opts.should == {:key => :value}
415
+ args.should == [:one, :two]
416
+ end
417
+
418
+ it "should return nil for the opts if no hash is provided" do
419
+ opts,args = the_method(:one, :two)
420
+ opts.should be_nil
421
+ args.should == [:one, :two]
422
+ end
423
+
424
+ it "should return two hashes" do
425
+ opts,args = the_method( {:one => :two}, :key => :value)
426
+ opts.should == {:key => :value}
427
+ args.should == [{:one => :two}]
428
+ end
429
+
430
+ end