rtomayko-sinatra 0.3.3 → 0.8.9

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 (81) hide show
  1. data/AUTHORS +40 -0
  2. data/CHANGES +167 -0
  3. data/README.rdoc +104 -98
  4. data/Rakefile +27 -9
  5. data/{test → compat}/app_test.rb +11 -10
  6. data/{test → compat}/application_test.rb +10 -5
  7. data/compat/builder_test.rb +101 -0
  8. data/{test → compat}/custom_error_test.rb +0 -0
  9. data/compat/erb_test.rb +136 -0
  10. data/{test → compat}/events_test.rb +12 -2
  11. data/compat/filter_test.rb +30 -0
  12. data/compat/haml_test.rb +233 -0
  13. data/compat/helper.rb +21 -0
  14. data/compat/mapped_error_test.rb +72 -0
  15. data/{test → compat}/pipeline_test.rb +9 -4
  16. data/{test → compat}/public/foo.xml +0 -0
  17. data/compat/sass_test.rb +57 -0
  18. data/{test → compat}/sessions_test.rb +0 -0
  19. data/{test → compat}/streaming_test.rb +4 -1
  20. data/{test → compat}/sym_params_test.rb +0 -0
  21. data/{test → compat}/template_test.rb +0 -0
  22. data/{test → compat}/use_in_file_templates_test.rb +0 -0
  23. data/{test → compat}/views/foo.builder +0 -0
  24. data/{test → compat}/views/foo.erb +0 -0
  25. data/{test → compat}/views/foo.haml +0 -0
  26. data/{test → compat}/views/foo.sass +0 -0
  27. data/{test → compat}/views/foo_layout.erb +0 -0
  28. data/{test → compat}/views/foo_layout.haml +0 -0
  29. data/{test → compat}/views/layout_test/foo.builder +0 -0
  30. data/{test → compat}/views/layout_test/foo.erb +0 -0
  31. data/{test → compat}/views/layout_test/foo.haml +0 -0
  32. data/{test → compat}/views/layout_test/foo.sass +0 -0
  33. data/{test → compat}/views/layout_test/layout.builder +0 -0
  34. data/{test → compat}/views/layout_test/layout.erb +0 -0
  35. data/{test → compat}/views/layout_test/layout.haml +0 -0
  36. data/{test → compat}/views/layout_test/layout.sass +0 -0
  37. data/{test → compat}/views/no_layout/no_layout.builder +0 -0
  38. data/{test → compat}/views/no_layout/no_layout.haml +0 -0
  39. data/lib/sinatra/base.rb +818 -0
  40. data/lib/sinatra/compat.rb +239 -0
  41. data/{images → lib/sinatra/images}/404.png +0 -0
  42. data/{images → lib/sinatra/images}/500.png +0 -0
  43. data/lib/sinatra/main.rb +48 -0
  44. data/lib/sinatra/test/rspec.rb +1 -9
  45. data/lib/sinatra/test/spec.rb +1 -9
  46. data/lib/sinatra/test/unit.rb +3 -5
  47. data/lib/sinatra/test.rb +112 -0
  48. data/lib/sinatra.rb +3 -1486
  49. data/sinatra.gemspec +66 -36
  50. data/test/base_test.rb +72 -0
  51. data/test/builder_test.rb +56 -89
  52. data/test/data/reload_app_file.rb +3 -0
  53. data/test/erb_test.rb +44 -125
  54. data/test/filter_test.rb +29 -20
  55. data/test/haml_test.rb +57 -218
  56. data/test/helpers_test.rb +368 -0
  57. data/test/mapped_error_test.rb +141 -49
  58. data/test/middleware_test.rb +63 -0
  59. data/test/options_test.rb +103 -0
  60. data/test/reload_test.rb +65 -0
  61. data/test/request_test.rb +11 -0
  62. data/test/result_test.rb +92 -0
  63. data/test/routing_test.rb +338 -0
  64. data/test/sass_test.rb +33 -50
  65. data/test/sinatra_test.rb +15 -0
  66. data/test/static_test.rb +60 -0
  67. data/test/templates_test.rb +92 -0
  68. data/test/views/hello.builder +1 -0
  69. data/test/views/hello.erb +1 -0
  70. data/test/views/hello.haml +1 -0
  71. data/test/views/hello.sass +2 -0
  72. data/test/views/hello.test +1 -0
  73. data/test/views/layout2.builder +3 -0
  74. data/test/views/layout2.erb +2 -0
  75. data/test/views/layout2.haml +2 -0
  76. data/test/views/layout2.test +1 -0
  77. metadata +78 -48
  78. data/ChangeLog +0 -96
  79. data/lib/sinatra/test/methods.rb +0 -76
  80. data/test/event_context_test.rb +0 -15
  81. data/test/helper.rb +0 -9
data/test/haml_test.rb CHANGED
@@ -1,233 +1,72 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- context "Haml" do
4
-
5
- setup do
6
- Sinatra.application = nil
1
+ require 'test/spec'
2
+ require 'sinatra/base'
3
+ require 'sinatra/test'
4
+
5
+ describe "HAML Templates" do
6
+ include Sinatra::Test
7
+
8
+ def haml_app(&block)
9
+ mock_app {
10
+ set :views, File.dirname(__FILE__) + '/views'
11
+ get '/', &block
12
+ }
13
+ get '/'
7
14
  end
8
15
 
9
- context "without layouts" do
10
-
11
- setup do
12
- Sinatra.application = nil
13
- end
14
-
15
- specify "should render" do
16
-
17
- get '/no_layout' do
18
- haml '== #{1+1}'
19
- end
20
-
21
- get_it '/no_layout'
22
- should.be.ok
23
- body.should == "2\n"
24
-
25
- end
16
+ it 'renders inline HAML strings' do
17
+ haml_app { haml '%h1 Hiya' }
18
+ should.be.ok
19
+ body.should.equal "<h1>Hiya</h1>\n"
26
20
  end
27
21
 
28
- context "with layouts" do
29
-
30
- setup do
31
- Sinatra.application = nil
32
- end
33
-
34
- specify "can be inline" do
35
-
36
- layout do
37
- '== This is #{yield}!'
38
- end
39
-
40
- get '/lay' do
41
- haml 'Blake'
42
- end
43
-
44
- get_it '/lay'
45
- should.be.ok
46
- body.should.equal "This is Blake\n!\n"
47
-
48
- end
49
-
50
- specify "can use named layouts" do
51
-
52
- layout :pretty do
53
- '%h1== #{yield}'
54
- end
55
-
56
- get '/pretty' do
57
- haml 'Foo', :layout => :pretty
58
- end
59
-
60
- get '/not_pretty' do
61
- haml 'Bar'
62
- end
63
-
64
- get_it '/pretty'
65
- body.should.equal "<h1>Foo</h1>\n"
66
-
67
- get_it '/not_pretty'
68
- body.should.equal "Bar\n"
69
-
70
- end
71
-
72
- specify "can be read from a file if they're not inlined" do
73
-
74
- get '/foo' do
75
- @title = 'Welcome to the Hello Program'
76
- haml 'Blake', :layout => :foo_layout,
77
- :views_directory => File.dirname(__FILE__) + "/views"
78
- end
79
-
80
- get_it '/foo'
81
- body.should.equal "Welcome to the Hello Program\nHi Blake\n"
82
-
83
- end
84
-
85
- specify "can be read from file and layout from text" do
86
- get '/foo' do
87
- haml 'Test', :layout => '== Foo #{yield}'
88
- end
89
-
90
- get_it '/foo'
91
-
92
- body.should.equal "Foo Test\n"
93
- end
94
-
22
+ it 'renders .haml files in views path' do
23
+ haml_app { haml :hello }
24
+ should.be.ok
25
+ body.should.equal "<h1>Hello From Haml</h1>\n"
95
26
  end
96
27
 
97
- context "Templates (in general)" do
98
-
99
- setup do
100
- Sinatra.application = nil
101
- end
102
-
103
- specify "are read from files if Symbols" do
104
-
105
- get '/from_file' do
106
- @name = 'Alena'
107
- haml :foo, :views_directory => File.dirname(__FILE__) + "/views"
108
- end
109
-
110
- get_it '/from_file'
111
-
112
- body.should.equal "You rock Alena!\n"
113
-
114
- end
115
-
116
- specify "use layout.ext by default if available" do
117
-
118
- get '/' do
119
- haml :foo, :views_directory => File.dirname(__FILE__) + "/views/layout_test"
120
- end
121
-
122
- get_it '/'
123
- should.be.ok
124
- body.should.equal "x This is foo!\n x\n"
125
-
126
- end
127
-
128
- specify "renders without layout" do
129
-
130
- get '/' do
131
- haml :no_layout, :views_directory => File.dirname(__FILE__) + "/views/no_layout"
132
- end
133
-
134
- get_it '/'
135
- should.be.ok
136
- body.should.equal "<h1>No Layout!</h1>\n"
137
-
138
- end
139
-
140
- specify "can render with no layout" do
141
- layout do
142
- "X\n= yield\nX"
143
- end
144
-
145
- get '/' do
146
- haml 'blake', :layout => false
147
- end
148
-
149
- get_it '/'
150
-
151
- body.should.equal "blake\n"
152
- end
153
-
154
- specify "raises error if template not found" do
155
- get '/' do
156
- haml :not_found
157
- end
158
-
159
- lambda { get_it '/' }.should.raise(Errno::ENOENT)
160
- end
161
-
162
- specify "use layout.ext by default if available" do
163
-
164
- template :foo do
165
- 'asdf'
166
- end
167
-
168
- get '/' do
169
- haml :foo, :layout => false,
170
- :views_directory => File.dirname(__FILE__) + "/views/layout_test"
171
- end
172
-
173
- get_it '/'
174
- should.be.ok
175
- body.should.equal "asdf\n"
176
-
177
- end
178
-
28
+ it "renders with inline layouts" do
29
+ mock_app {
30
+ layout { %q(%h1= 'THIS. IS. ' + yield.upcase) }
31
+ get('/') { haml '%em Sparta' }
32
+ }
33
+ get '/'
34
+ should.be.ok
35
+ body.should.equal "<h1>THIS. IS. <EM>SPARTA</EM></h1>\n"
179
36
  end
180
37
 
181
- describe 'Options passed to the HAML interpreter' do
182
- setup do
183
- Sinatra.application = nil
184
- end
185
-
186
- specify 'are empty be default' do
187
-
188
- get '/' do
189
- haml 'foo'
190
- end
191
-
192
- Haml::Engine.expects(:new).with('foo', {}).returns(stub(:render => 'foo'))
193
-
194
- get_it '/'
195
- should.be.ok
196
-
197
- end
198
-
199
- specify 'can be configured by passing :options to haml' do
200
-
201
- get '/' do
202
- haml 'foo', :options => {:format => :html4}
203
- end
204
-
205
- Haml::Engine.expects(:new).with('foo', {:format => :html4}).returns(stub(:render => 'foo'))
206
-
207
- get_it '/'
208
- should.be.ok
209
-
210
- end
38
+ it "renders with file layouts" do
39
+ haml_app {
40
+ haml 'Hello World', :layout => :layout2
41
+ }
42
+ should.be.ok
43
+ body.should.equal "<h1>HAML Layout!</h1>\n<p>Hello World</p>\n"
44
+ end
211
45
 
212
- specify 'can be configured using set_option :haml' do
46
+ it "raises error if template not found" do
47
+ mock_app {
48
+ get('/') { haml :no_such_template }
49
+ }
50
+ lambda { get('/') }.should.raise(Errno::ENOENT)
51
+ end
213
52
 
214
- configure do
215
- set_option :haml, :format => :html4,
216
- :escape_html => true
217
- end
53
+ it "passes HAML options to the Haml engine" do
54
+ haml_app {
55
+ haml "!!!\n%h1 Hello World", :options => {:format => :html5}
56
+ }
57
+ should.be.ok
58
+ body.should.equal "<!DOCTYPE html>\n<h1>Hello World</h1>\n"
59
+ end
218
60
 
61
+ it "passes default HAML options to the Haml engine" do
62
+ mock_app {
63
+ set :haml, {:format => :html5}
219
64
  get '/' do
220
- haml 'foo'
65
+ haml "!!!\n%h1 Hello World"
221
66
  end
222
-
223
- Haml::Engine.expects(:new).with('foo', {:format => :html4,
224
- :escape_html => true}).returns(stub(:render => 'foo'))
225
-
226
- get_it '/'
227
- should.be.ok
228
-
229
- end
230
-
67
+ }
68
+ get '/'
69
+ should.be.ok
70
+ body.should.equal "<!DOCTYPE html>\n<h1>Hello World</h1>\n"
231
71
  end
232
-
233
72
  end
@@ -0,0 +1,368 @@
1
+ require 'test/spec'
2
+ require 'sinatra/base'
3
+ require 'sinatra/test'
4
+
5
+ class Test::Unit::TestCase
6
+ include Sinatra::Test
7
+ end
8
+
9
+ describe 'Sinatra::Helpers' do
10
+ describe '#status' do
11
+ setup do
12
+ mock_app {
13
+ get '/' do
14
+ status 207
15
+ nil
16
+ end
17
+ }
18
+ end
19
+
20
+ it 'sets the response status code' do
21
+ get '/'
22
+ response.status.should.equal 207
23
+ end
24
+ end
25
+
26
+ describe '#body' do
27
+ it 'takes a block for defered body generation' do
28
+ mock_app {
29
+ get '/' do
30
+ body { 'Hello World' }
31
+ end
32
+ }
33
+
34
+ get '/'
35
+ body.should.equal 'Hello World'
36
+ end
37
+
38
+ it 'takes a String, Array, or other object responding to #each' do
39
+ mock_app {
40
+ get '/' do
41
+ body 'Hello World'
42
+ end
43
+ }
44
+
45
+ get '/'
46
+ body.should.equal 'Hello World'
47
+ end
48
+ end
49
+
50
+ describe '#redirect' do
51
+ it 'uses a 302 when only a path is given' do
52
+ mock_app {
53
+ get '/' do
54
+ redirect '/foo'
55
+ fail 'redirect should halt'
56
+ end
57
+ }
58
+
59
+ get '/'
60
+ status.should.equal 302
61
+ body.should.be.empty
62
+ response['Location'].should.equal '/foo'
63
+ end
64
+
65
+ it 'uses the code given when specified' do
66
+ mock_app {
67
+ get '/' do
68
+ redirect '/foo', 301
69
+ fail 'redirect should halt'
70
+ end
71
+ }
72
+
73
+ get '/'
74
+ status.should.equal 301
75
+ body.should.be.empty
76
+ response['Location'].should.equal '/foo'
77
+ end
78
+ end
79
+
80
+ describe '#error' do
81
+ it 'sets a status code and halts' do
82
+ mock_app {
83
+ get '/' do
84
+ error 501
85
+ fail 'error should halt'
86
+ end
87
+ }
88
+
89
+ get '/'
90
+ status.should.equal 501
91
+ body.should.be.empty
92
+ end
93
+
94
+ it 'takes an optional body' do
95
+ mock_app {
96
+ get '/' do
97
+ error 501, 'FAIL'
98
+ fail 'error should halt'
99
+ end
100
+ }
101
+
102
+ get '/'
103
+ status.should.equal 501
104
+ body.should.equal 'FAIL'
105
+ end
106
+
107
+ it 'uses a 500 status code when first argument is a body' do
108
+ mock_app {
109
+ get '/' do
110
+ error 'FAIL'
111
+ fail 'error should halt'
112
+ end
113
+ }
114
+
115
+ get '/'
116
+ status.should.equal 500
117
+ body.should.equal 'FAIL'
118
+ end
119
+ end
120
+
121
+ describe '#not_found' do
122
+ it 'halts with a 404 status' do
123
+ mock_app {
124
+ get '/' do
125
+ not_found
126
+ fail 'not_found should halt'
127
+ end
128
+ }
129
+
130
+ get '/'
131
+ status.should.equal 404
132
+ body.should.be.empty
133
+ end
134
+ end
135
+
136
+ describe '#session' do
137
+ it 'uses the existing rack.session' do
138
+ mock_app {
139
+ get '/' do
140
+ session[:foo]
141
+ end
142
+ }
143
+
144
+ get '/', :env => { 'rack.session' => { :foo => 'bar' } }
145
+ body.should.equal 'bar'
146
+ end
147
+
148
+ it 'creates a new session when none provided' do
149
+ mock_app {
150
+ get '/' do
151
+ session.should.be.empty
152
+ session[:foo] = 'bar'
153
+ 'Hi'
154
+ end
155
+ }
156
+
157
+ get '/'
158
+ body.should.equal 'Hi'
159
+ end
160
+ end
161
+
162
+ describe '#media_type' do
163
+ include Sinatra::Helpers
164
+ it "looks up media types in Rack's MIME registry" do
165
+ Rack::Mime::MIME_TYPES['.foo'] = 'application/foo'
166
+ media_type('foo').should.equal 'application/foo'
167
+ media_type('.foo').should.equal 'application/foo'
168
+ media_type(:foo).should.equal 'application/foo'
169
+ end
170
+ it 'returns nil when given nil' do
171
+ media_type(nil).should.be.nil
172
+ end
173
+ it 'returns nil when media type not registered' do
174
+ media_type(:bizzle).should.be.nil
175
+ end
176
+ it 'returns the argument when given a media type string' do
177
+ media_type('text/plain').should.equal 'text/plain'
178
+ end
179
+ end
180
+
181
+ describe '#content_type' do
182
+ it 'sets the Content-Type header' do
183
+ mock_app {
184
+ get '/' do
185
+ content_type 'text/plain'
186
+ 'Hello World'
187
+ end
188
+ }
189
+
190
+ get '/'
191
+ response['Content-Type'].should.equal 'text/plain'
192
+ body.should.equal 'Hello World'
193
+ end
194
+
195
+ it 'takes media type parameters (like charset=)' do
196
+ mock_app {
197
+ get '/' do
198
+ content_type 'text/html', :charset => 'utf-8'
199
+ "<h1>Hello, World</h1>"
200
+ end
201
+ }
202
+
203
+ get '/'
204
+ should.be.ok
205
+ response['Content-Type'].should.equal 'text/html;charset=utf-8'
206
+ body.should.equal "<h1>Hello, World</h1>"
207
+ end
208
+
209
+ it "looks up symbols in Rack's mime types dictionary" do
210
+ Rack::Mime::MIME_TYPES['.foo'] = 'application/foo'
211
+ mock_app {
212
+ get '/foo.xml' do
213
+ content_type :foo
214
+ "I AM FOO"
215
+ end
216
+ }
217
+
218
+ get '/foo.xml'
219
+ should.be.ok
220
+ response['Content-Type'].should.equal 'application/foo'
221
+ body.should.equal 'I AM FOO'
222
+ end
223
+
224
+ it 'fails when no mime type is registered for the argument provided' do
225
+ mock_app {
226
+ get '/foo.xml' do
227
+ content_type :bizzle
228
+ "I AM FOO"
229
+ end
230
+ }
231
+
232
+ lambda { get '/foo.xml' }.should.raise RuntimeError
233
+ end
234
+ end
235
+
236
+ describe '#send_file' do
237
+ before {
238
+ @file = File.dirname(__FILE__) + '/file.txt'
239
+ File.open(@file, 'wb') { |io| io.write('Hello World') }
240
+ }
241
+ after {
242
+ File.unlink @file
243
+ @file = nil
244
+ }
245
+
246
+ def send_file_app
247
+ path = @file
248
+ mock_app {
249
+ get '/file.txt' do
250
+ send_file path
251
+ end
252
+ }
253
+ end
254
+
255
+ it "sends the contents of the file" do
256
+ send_file_app
257
+ get '/file.txt'
258
+ should.be.ok
259
+ body.should.equal 'Hello World'
260
+ end
261
+
262
+ it 'sets the Content-Type response header if a mime-type can be located' do
263
+ send_file_app
264
+ get '/file.txt'
265
+ response['Content-Type'].should.equal 'text/plain'
266
+ end
267
+
268
+ it 'sets the Content-Length response header' do
269
+ send_file_app
270
+ get '/file.txt'
271
+ response['Content-Length'].should.equal 'Hello World'.length.to_s
272
+ end
273
+
274
+ it 'sets the Last-Modified response header' do
275
+ send_file_app
276
+ get '/file.txt'
277
+ response['Last-Modified'].should.equal File.mtime(@file).httpdate
278
+ end
279
+
280
+ it "returns a 404 when not found" do
281
+ mock_app {
282
+ get '/' do
283
+ send_file 'this-file-does-not-exist.txt'
284
+ end
285
+ }
286
+ get '/'
287
+ should.be.not_found
288
+ end
289
+ end
290
+
291
+ describe '#last_modified' do
292
+ before do
293
+ now = Time.now
294
+ mock_app {
295
+ get '/' do
296
+ body { 'Hello World' }
297
+ last_modified now
298
+ 'Boo!'
299
+ end
300
+ }
301
+ @now = now
302
+ end
303
+
304
+ it 'sets the Last-Modified header to a valid RFC 2616 date value' do
305
+ get '/'
306
+ response['Last-Modified'].should.equal @now.httpdate
307
+ end
308
+
309
+ it 'returns a body when conditional get misses' do
310
+ get '/'
311
+ status.should.be 200
312
+ body.should.equal 'Boo!'
313
+ end
314
+
315
+ it 'halts when a conditional GET matches' do
316
+ get '/', :env => { 'HTTP_IF_MODIFIED_SINCE' => @now.httpdate }
317
+ status.should.be 304
318
+ body.should.be.empty
319
+ end
320
+ end
321
+
322
+ describe '#etag' do
323
+ before do
324
+ mock_app {
325
+ get '/' do
326
+ body { 'Hello World' }
327
+ etag 'FOO'
328
+ 'Boo!'
329
+ end
330
+ }
331
+ end
332
+
333
+ it 'sets the ETag header' do
334
+ get '/'
335
+ response['ETag'].should.equal '"FOO"'
336
+ end
337
+
338
+ it 'returns a body when conditional get misses' do
339
+ get '/'
340
+ status.should.be 200
341
+ body.should.equal 'Boo!'
342
+ end
343
+
344
+ it 'halts when a conditional GET matches' do
345
+ get '/', :env => { 'HTTP_IF_NONE_MATCH' => '"FOO"' }
346
+ status.should.be 304
347
+ body.should.be.empty
348
+ end
349
+
350
+ it 'should handle multiple ETag values in If-None-Match header' do
351
+ get '/', :env => { 'HTTP_IF_NONE_MATCH' => '"BAR", *' }
352
+ status.should.be 304
353
+ body.should.be.empty
354
+ end
355
+
356
+ it 'uses a weak etag with the :weak option' do
357
+ mock_app {
358
+ get '/' do
359
+ etag 'FOO', :weak
360
+ "that's weak, dude."
361
+ end
362
+ }
363
+ get '/'
364
+ response['ETag'].should.equal 'W/"FOO"'
365
+ end
366
+
367
+ end
368
+ end