Syd-sinatra 0.3.2 → 0.9.0.2

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