Syd-sinatra 0.3.2

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 (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 +1470 -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