bmizerany-sinatra 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/ChangeLog +78 -0
  2. data/LICENSE +22 -0
  3. data/README.rdoc +523 -0
  4. data/Rakefile +162 -0
  5. data/images/404.png +0 -0
  6. data/images/500.png +0 -0
  7. data/lib/sinatra/test/methods.rb +76 -0
  8. data/lib/sinatra/test/rspec.rb +10 -0
  9. data/lib/sinatra/test/spec.rb +10 -0
  10. data/lib/sinatra/test/unit.rb +13 -0
  11. data/lib/sinatra.rb +1466 -0
  12. data/sinatra.gemspec +77 -0
  13. data/test/app_test.rb +299 -0
  14. data/test/application_test.rb +318 -0
  15. data/test/builder_test.rb +101 -0
  16. data/test/custom_error_test.rb +62 -0
  17. data/test/erb_test.rb +136 -0
  18. data/test/event_context_test.rb +15 -0
  19. data/test/events_test.rb +65 -0
  20. data/test/filter_test.rb +30 -0
  21. data/test/haml_test.rb +233 -0
  22. data/test/helper.rb +7 -0
  23. data/test/mapped_error_test.rb +72 -0
  24. data/test/pipeline_test.rb +66 -0
  25. data/test/public/foo.xml +1 -0
  26. data/test/sass_test.rb +57 -0
  27. data/test/sessions_test.rb +39 -0
  28. data/test/streaming_test.rb +118 -0
  29. data/test/sym_params_test.rb +19 -0
  30. data/test/template_test.rb +30 -0
  31. data/test/use_in_file_templates_test.rb +47 -0
  32. data/test/views/foo.builder +1 -0
  33. data/test/views/foo.erb +1 -0
  34. data/test/views/foo.haml +1 -0
  35. data/test/views/foo.sass +2 -0
  36. data/test/views/foo_layout.erb +2 -0
  37. data/test/views/foo_layout.haml +2 -0
  38. data/test/views/layout_test/foo.builder +1 -0
  39. data/test/views/layout_test/foo.erb +1 -0
  40. data/test/views/layout_test/foo.haml +1 -0
  41. data/test/views/layout_test/foo.sass +2 -0
  42. data/test/views/layout_test/layout.builder +3 -0
  43. data/test/views/layout_test/layout.erb +1 -0
  44. data/test/views/layout_test/layout.haml +1 -0
  45. data/test/views/layout_test/layout.sass +2 -0
  46. data/test/views/no_layout/no_layout.builder +1 -0
  47. data/test/views/no_layout/no_layout.haml +1 -0
  48. metadata +129 -0
data/sinatra.gemspec ADDED
@@ -0,0 +1,77 @@
1
+ Gem::Specification.new do |s|
2
+ s.specification_version = 2 if s.respond_to? :specification_version=
3
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
+
5
+ s.name = 'sinatra'
6
+ s.version = '0.3.2'
7
+ s.date = "2008-11-02"
8
+
9
+ s.description = "Classy web-development dressed in a DSL"
10
+ s.summary = "Classy web-development dressed in a DSL"
11
+
12
+ s.authors = ["Blake Mizerany"]
13
+
14
+ # = MANIFEST =
15
+ s.files = %w[
16
+ ChangeLog
17
+ LICENSE
18
+ README.rdoc
19
+ Rakefile
20
+ images/404.png
21
+ images/500.png
22
+ lib/sinatra.rb
23
+ lib/sinatra/test/methods.rb
24
+ lib/sinatra/test/rspec.rb
25
+ lib/sinatra/test/spec.rb
26
+ lib/sinatra/test/unit.rb
27
+ sinatra.gemspec
28
+ test/app_test.rb
29
+ test/application_test.rb
30
+ test/builder_test.rb
31
+ test/custom_error_test.rb
32
+ test/erb_test.rb
33
+ test/event_context_test.rb
34
+ test/events_test.rb
35
+ test/filter_test.rb
36
+ test/haml_test.rb
37
+ test/helper.rb
38
+ test/mapped_error_test.rb
39
+ test/pipeline_test.rb
40
+ test/public/foo.xml
41
+ test/sass_test.rb
42
+ test/sessions_test.rb
43
+ test/streaming_test.rb
44
+ test/sym_params_test.rb
45
+ test/template_test.rb
46
+ test/use_in_file_templates_test.rb
47
+ test/views/foo.builder
48
+ test/views/foo.erb
49
+ test/views/foo.haml
50
+ test/views/foo.sass
51
+ test/views/foo_layout.erb
52
+ test/views/foo_layout.haml
53
+ test/views/layout_test/foo.builder
54
+ test/views/layout_test/foo.erb
55
+ test/views/layout_test/foo.haml
56
+ test/views/layout_test/foo.sass
57
+ test/views/layout_test/layout.builder
58
+ test/views/layout_test/layout.erb
59
+ test/views/layout_test/layout.haml
60
+ test/views/layout_test/layout.sass
61
+ test/views/no_layout/no_layout.builder
62
+ test/views/no_layout/no_layout.haml
63
+ ]
64
+ # = MANIFEST =
65
+
66
+ s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
67
+
68
+ s.extra_rdoc_files = %w[README.rdoc LICENSE]
69
+ s.add_dependency 'rack', '>= 0.4.0'
70
+
71
+ s.has_rdoc = true
72
+ s.homepage = "http://sinatra.rubyforge.org"
73
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Sinatra", "--main", "README.rdoc"]
74
+ s.require_paths = %w[lib]
75
+ s.rubyforge_project = 'sinatra'
76
+ s.rubygems_version = '1.1.1'
77
+ end
data/test/app_test.rb ADDED
@@ -0,0 +1,299 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "Sinatra" do
4
+
5
+ setup do
6
+ Sinatra.application = nil
7
+ end
8
+
9
+ specify "should put all DSL methods on (main)" do
10
+ object = Object.new
11
+ Sinatra::Application::FORWARD_METHODS.each do |method|
12
+ object.private_methods.should.include(method)
13
+ end
14
+ end
15
+
16
+ specify "should handle result of nil" do
17
+ get '/' do
18
+ nil
19
+ end
20
+
21
+ get_it '/'
22
+ should.be.ok
23
+ body.should == ''
24
+ end
25
+
26
+ specify "handles events" do
27
+ get '/:name' do
28
+ 'Hello ' + params["name"]
29
+ end
30
+
31
+ get_it '/Blake'
32
+
33
+ should.be.ok
34
+ body.should.equal 'Hello Blake'
35
+ end
36
+
37
+
38
+ specify "handles splats" do
39
+ get '/hi/*' do
40
+ params["splat"].kind_of?(Array).should.equal true
41
+ params["splat"].first
42
+ end
43
+
44
+ get_it '/hi/Blake'
45
+
46
+ should.be.ok
47
+ body.should.equal 'Blake'
48
+ end
49
+
50
+ specify "handles multiple splats" do
51
+ get '/say/*/to/*' do
52
+ params["splat"].join(' ')
53
+ end
54
+
55
+ get_it '/say/hello/to/world'
56
+
57
+ should.be.ok
58
+ body.should.equal 'hello world'
59
+ end
60
+
61
+ specify "allow empty splats" do
62
+ get '/say/*/to*/*' do
63
+ params["splat"].join(' ')
64
+ end
65
+
66
+ get_it '/say/hello/to/world'
67
+
68
+ should.be.ok
69
+ body.should.equal 'hello world' # second splat is empty
70
+
71
+ get_it '/say/hello/tomy/world'
72
+
73
+ should.be.ok
74
+ body.should.equal 'hello my world'
75
+ end
76
+
77
+ specify "gives access to underlying response header Hash" do
78
+ get '/' do
79
+ header['X-Test'] = 'Is this thing on?'
80
+ headers 'X-Test2' => 'Foo', 'X-Test3' => 'Bar'
81
+ ''
82
+ end
83
+
84
+ get_it '/'
85
+ should.be.ok
86
+ headers.should.include 'X-Test'
87
+ headers['X-Test'].should.equal 'Is this thing on?'
88
+ headers.should.include 'X-Test3'
89
+ headers['X-Test3'].should.equal 'Bar'
90
+ end
91
+
92
+ specify "follows redirects" do
93
+ get '/' do
94
+ redirect '/blake'
95
+ end
96
+
97
+ get '/blake' do
98
+ 'Mizerany'
99
+ end
100
+
101
+ get_it '/'
102
+ should.be.redirection
103
+ body.should.equal ''
104
+
105
+ follow!
106
+ should.be.ok
107
+ body.should.equal 'Mizerany'
108
+ end
109
+
110
+ specify "renders a body with a redirect" do
111
+ Sinatra::EventContext.any_instance.expects(:foo).returns('blah')
112
+ get "/" do
113
+ redirect 'foo', :foo
114
+ end
115
+ get_it '/'
116
+ should.be.redirection
117
+ headers['Location'].should.equal 'foo'
118
+ body.should.equal 'blah'
119
+ end
120
+
121
+ specify "redirects permanently with 301 status code" do
122
+ get "/" do
123
+ redirect 'foo', 301
124
+ end
125
+ get_it '/'
126
+ should.be.redirection
127
+ headers['Location'].should.equal 'foo'
128
+ status.should.equal 301
129
+ body.should.be.empty
130
+ end
131
+
132
+ specify "stop sets content and ends event" do
133
+
134
+ Sinatra::EventContext.any_instance.expects(:foo).never
135
+
136
+ get '/set_body' do
137
+ stop 'Hello!'
138
+ stop 'World!'
139
+ foo
140
+ end
141
+
142
+ get_it '/set_body'
143
+
144
+ should.be.ok
145
+ body.should.equal 'Hello!'
146
+
147
+ end
148
+
149
+ specify "should set status then call helper with a var" do
150
+ Sinatra::EventContext.any_instance.expects(:foo).once.with(1).returns('bah!')
151
+
152
+ get '/set_body' do
153
+ stop [404, [:foo, 1]]
154
+ end
155
+
156
+ get_it '/set_body'
157
+
158
+ should.be.not_found
159
+ body.should.equal 'bah!'
160
+
161
+ end
162
+
163
+ specify "should easily set response Content-Type" do
164
+ get '/foo.html' do
165
+ content_type 'text/html', :charset => 'utf-8'
166
+ "<h1>Hello, World</h1>"
167
+ end
168
+
169
+ get_it '/foo.html'
170
+ should.be.ok
171
+ headers['Content-Type'].should.equal 'text/html;charset=utf-8'
172
+ body.should.equal '<h1>Hello, World</h1>'
173
+
174
+ get '/foo_test.xml' do
175
+ content_type :xml
176
+ "<feed></feed>"
177
+ end
178
+
179
+ get_it '/foo_test.xml'
180
+ should.be.ok
181
+ headers['Content-Type'].should.equal 'application/xml'
182
+ body.should.equal '<feed></feed>'
183
+ end
184
+
185
+ specify "supports conditional GETs with last_modified" do
186
+ modified_at = Time.now
187
+ get '/maybe' do
188
+ last_modified modified_at
189
+ 'response body, maybe'
190
+ end
191
+
192
+ get_it '/maybe'
193
+ should.be.ok
194
+ body.should.equal 'response body, maybe'
195
+
196
+ get_it '/maybe', :env => { 'HTTP_IF_MODIFIED_SINCE' => modified_at.httpdate }
197
+ status.should.equal 304
198
+ body.should.equal ''
199
+ end
200
+
201
+ specify "supports conditional GETs with entity_tag" do
202
+ get '/strong' do
203
+ entity_tag 'FOO'
204
+ 'foo response'
205
+ end
206
+
207
+ get_it '/strong'
208
+ should.be.ok
209
+ body.should.equal 'foo response'
210
+
211
+ get_it '/strong', {},
212
+ 'HTTP_IF_NONE_MATCH' => '"BAR"'
213
+ should.be.ok
214
+ body.should.equal 'foo response'
215
+
216
+ get_it '/strong', {},
217
+ 'HTTP_IF_NONE_MATCH' => '"FOO"'
218
+ status.should.equal 304
219
+ body.should.equal ''
220
+
221
+ get_it '/strong', {},
222
+ 'HTTP_IF_NONE_MATCH' => '"BAR", *'
223
+ status.should.equal 304
224
+ body.should.equal ''
225
+ end
226
+
227
+ specify "delegates HEAD requests to GET handlers" do
228
+ get '/invisible' do
229
+ "I am invisible to the world"
230
+ end
231
+
232
+ head_it '/invisible'
233
+ should.be.ok
234
+ body.should.not.equal "I am invisible to the world"
235
+ body.should.equal ''
236
+ end
237
+
238
+
239
+ specify "supports PUT" do
240
+ put '/' do
241
+ 'puted'
242
+ end
243
+ put_it '/'
244
+ assert_equal 'puted', body
245
+ end
246
+
247
+ specify "rewrites POSTs with _method param to PUT" do
248
+ put '/' do
249
+ 'puted'
250
+ end
251
+ post_it '/', :_method => 'PUT'
252
+ assert_equal 'puted', body
253
+ end
254
+
255
+ # Some Ajax libraries downcase the _method parameter value. Make
256
+ # sure we can handle that.
257
+ specify "rewrites POSTs with lowercase _method param to PUT" do
258
+ put '/' do
259
+ 'puted'
260
+ end
261
+ post_it '/', :_method => 'put'
262
+ body.should.equal 'puted'
263
+ end
264
+
265
+ # Ignore any _method parameters specified in GET requests or on the query string in POST requests.
266
+ specify "does not rewrite GETs with _method param to PUT" do
267
+ get '/' do
268
+ 'getted'
269
+ end
270
+ get_it '/', :_method => 'put'
271
+ should.be.ok
272
+ body.should.equal 'getted'
273
+ end
274
+
275
+ specify "ignores _method query string parameter on non-POST requests" do
276
+ post '/' do
277
+ 'posted'
278
+ end
279
+ put '/' do
280
+ 'booo'
281
+ end
282
+ post_it "/?_method=PUT"
283
+ should.be.ok
284
+ body.should.equal 'posted'
285
+ end
286
+
287
+ specify "does not read body if content type is not url encoded" do
288
+ post '/foo.xml' do
289
+ request.env['CONTENT_TYPE'].should.be == 'application/xml'
290
+ request.content_type.should.be == 'application/xml'
291
+ request.body.read
292
+ end
293
+
294
+ post_it '/foo.xml', '<foo></foo>', :content_type => 'application/xml'
295
+ @response.should.be.ok
296
+ @response.body.should.be == '<foo></foo>'
297
+ end
298
+
299
+ end
@@ -0,0 +1,318 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ require 'uri'
4
+
5
+ class TesterWithEach
6
+ def each
7
+ yield 'foo'
8
+ yield 'bar'
9
+ yield 'baz'
10
+ end
11
+ end
12
+
13
+ context "Looking up a request" do
14
+
15
+ setup do
16
+ Sinatra.application = nil
17
+ end
18
+
19
+ specify "returns what's at the end" do
20
+ block = Proc.new { 'Hello' }
21
+ get '/', &block
22
+
23
+ result = Sinatra.application.lookup(
24
+ Rack::Request.new(
25
+ 'REQUEST_METHOD' => 'GET',
26
+ 'PATH_INFO' => '/'
27
+ )
28
+ )
29
+
30
+ result.should.not.be.nil
31
+ result.block.should.be block
32
+ end
33
+
34
+ specify "takes params in path" do
35
+ block = Proc.new { 'Hello' }
36
+ get '/:foo', &block
37
+
38
+ result = Sinatra.application.lookup(
39
+ Rack::Request.new(
40
+ 'REQUEST_METHOD' => 'GET',
41
+ 'PATH_INFO' => '/bar'
42
+ )
43
+ )
44
+
45
+ result.should.not.be.nil
46
+ result.block.should.be block
47
+ result.params.should.equal "foo" => 'bar'
48
+ end
49
+
50
+ end
51
+
52
+ context "An app returns" do
53
+
54
+ setup do
55
+ Sinatra.application = nil
56
+ end
57
+
58
+ specify "404 if no events found" do
59
+ request = Rack::MockRequest.new(@app)
60
+ get_it '/'
61
+ should.be.not_found
62
+ body.should.equal '<h1>Not Found</h1>'
63
+ end
64
+
65
+ specify "200 if success" do
66
+ get '/' do
67
+ 'Hello World'
68
+ end
69
+ get_it '/'
70
+ should.be.ok
71
+ body.should.equal 'Hello World'
72
+ end
73
+
74
+ specify "an objects result from each if it has it" do
75
+
76
+ get '/' do
77
+ TesterWithEach.new
78
+ end
79
+
80
+ get_it '/'
81
+ should.be.ok
82
+ body.should.equal 'foobarbaz'
83
+
84
+ end
85
+
86
+ specify "the body set if set before the last" do
87
+
88
+ get '/' do
89
+ body 'Blake'
90
+ 'Mizerany'
91
+ end
92
+
93
+ get_it '/'
94
+ should.be.ok
95
+ body.should.equal 'Blake'
96
+
97
+ end
98
+
99
+ end
100
+
101
+ context "Application#configure blocks" do
102
+
103
+ setup do
104
+ Sinatra.application = nil
105
+ end
106
+
107
+ specify "run when no environment specified" do
108
+ ref = false
109
+ configure { ref = true }
110
+ ref.should.equal true
111
+ end
112
+
113
+ specify "run when matching environment specified" do
114
+ ref = false
115
+ configure(:test) { ref = true }
116
+ ref.should.equal true
117
+ end
118
+
119
+ specify "do not run when no matching environment specified" do
120
+ configure(:foo) { flunk "block should not have been executed" }
121
+ configure(:development, :production, :foo) { flunk "block should not have been executed" }
122
+ end
123
+
124
+ specify "accept multiple environments" do
125
+ ref = false
126
+ configure(:foo, :test, :bar) { ref = true }
127
+ ref.should.equal true
128
+ end
129
+
130
+ end
131
+
132
+ context "Default Application Configuration" do
133
+
134
+ specify "includes 404 and 500 error handlers" do
135
+ Sinatra.application.errors.should.include(Sinatra::ServerError)
136
+ Sinatra.application.errors[Sinatra::ServerError].should.not.be.nil
137
+ Sinatra.application.errors.should.include(Sinatra::NotFound)
138
+ Sinatra.application.errors[Sinatra::NotFound].should.not.be.nil
139
+ end
140
+
141
+ specify "includes Static event" do
142
+ assert Sinatra.application.events[:get].any? { |e| Sinatra::Static === e }
143
+ end
144
+
145
+ end
146
+
147
+ context "Events in an app" do
148
+
149
+ setup do
150
+ Sinatra.application = nil
151
+ end
152
+
153
+ specify "evaluate in a clean context" do
154
+ helpers do
155
+ def foo
156
+ 'foo'
157
+ end
158
+ end
159
+
160
+ get '/foo' do
161
+ foo
162
+ end
163
+
164
+ get_it '/foo'
165
+ should.be.ok
166
+ body.should.equal 'foo'
167
+ end
168
+
169
+ specify "get access to request, response, and params" do
170
+ get '/:foo' do
171
+ params["foo"] + params["bar"]
172
+ end
173
+
174
+ get_it '/foo?bar=baz'
175
+ should.be.ok
176
+ body.should.equal 'foobaz'
177
+ end
178
+
179
+ specify "can filters by agent" do
180
+
181
+ get '/', :agent => /Windows/ do
182
+ request.env['HTTP_USER_AGENT']
183
+ end
184
+
185
+ get_it '/', :env => { :agent => 'Windows' }
186
+ should.be.ok
187
+ body.should.equal 'Windows'
188
+
189
+ get_it '/', :env => { :agent => 'Mac' }
190
+ should.not.be.ok
191
+
192
+ end
193
+
194
+ specify "can use regex to get parts of user-agent" do
195
+
196
+ get '/', :agent => /Windows (NT)/ do
197
+ params[:agent].first
198
+ end
199
+
200
+ get_it '/', :env => { :agent => 'Windows NT' }
201
+
202
+ body.should.equal 'NT'
203
+
204
+ end
205
+
206
+ specify "can deal with spaces in paths" do
207
+
208
+ path = '/path with spaces'
209
+
210
+ get path do
211
+ "Look ma, a path with spaces!"
212
+ end
213
+
214
+ get_it URI.encode(path)
215
+
216
+ body.should.equal "Look ma, a path with spaces!"
217
+ end
218
+
219
+ specify "route based on host" do
220
+
221
+ get '/' do
222
+ 'asdf'
223
+ end
224
+
225
+ get_it '/'
226
+ assert ok?
227
+ assert_equal('asdf', body)
228
+
229
+ get '/foo', :host => 'foo.sinatrarb.com' do
230
+ 'in foo!'
231
+ end
232
+
233
+ get '/foo', :host => 'bar.sinatrarb.com' do
234
+ 'in bar!'
235
+ end
236
+
237
+ get_it '/foo', {}, 'HTTP_HOST' => 'foo.sinatrarb.com'
238
+ assert ok?
239
+ assert_equal 'in foo!', body
240
+
241
+ get_it '/foo', {}, 'HTTP_HOST' => 'bar.sinatrarb.com'
242
+ assert ok?
243
+ assert_equal 'in bar!', body
244
+
245
+ get_it '/foo'
246
+ assert not_found?
247
+
248
+ end
249
+
250
+ end
251
+
252
+
253
+ context "Options in an app" do
254
+
255
+ setup do
256
+ Sinatra.application = nil
257
+ @app = Sinatra::application
258
+ end
259
+
260
+ specify "can be set singly on app" do
261
+ @app.set :foo, 1234
262
+ @app.options.foo.should.equal 1234
263
+ end
264
+
265
+ specify "can be set singly from top-level" do
266
+ set_option :foo, 1234
267
+ @app.options.foo.should.equal 1234
268
+ end
269
+
270
+ specify "can be set multiply on app" do
271
+ @app.options.foo.should.be.nil
272
+ @app.set :foo => 1234,
273
+ :bar => 'hello, world'
274
+ @app.options.foo.should.equal 1234
275
+ @app.options.bar.should.equal 'hello, world'
276
+ end
277
+
278
+ specify "can be set multiply from top-level" do
279
+ @app.options.foo.should.be.nil
280
+ set_options :foo => 1234,
281
+ :bar => 'hello, world'
282
+ @app.options.foo.should.equal 1234
283
+ @app.options.bar.should.equal 'hello, world'
284
+ end
285
+
286
+ specify "can be enabled on app" do
287
+ @app.options.foo.should.be.nil
288
+ @app.enable :sessions, :foo, :bar
289
+ @app.options.sessions.should.equal true
290
+ @app.options.foo.should.equal true
291
+ @app.options.bar.should.equal true
292
+ end
293
+
294
+ specify "can be enabled from top-level" do
295
+ @app.options.foo.should.be.nil
296
+ enable :sessions, :foo, :bar
297
+ @app.options.sessions.should.equal true
298
+ @app.options.foo.should.equal true
299
+ @app.options.bar.should.equal true
300
+ end
301
+
302
+ specify "can be disabled on app" do
303
+ @app.options.foo.should.be.nil
304
+ @app.disable :sessions, :foo, :bar
305
+ @app.options.sessions.should.equal false
306
+ @app.options.foo.should.equal false
307
+ @app.options.bar.should.equal false
308
+ end
309
+
310
+ specify "can be enabled from top-level" do
311
+ @app.options.foo.should.be.nil
312
+ disable :sessions, :foo, :bar
313
+ @app.options.sessions.should.equal false
314
+ @app.options.foo.should.equal false
315
+ @app.options.bar.should.equal false
316
+ end
317
+
318
+ end