sinatra 1.3.6 → 1.4.0.a

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sinatra might be problematic. Click here for more details.

Files changed (71) hide show
  1. data/CHANGES +96 -22
  2. data/Gemfile +11 -3
  3. data/README.de.md +2590 -0
  4. data/README.es.rdoc +66 -38
  5. data/README.fr.md +2630 -0
  6. data/README.hu.rdoc +3 -2
  7. data/README.jp.rdoc +16 -3
  8. data/README.ko.rdoc +11 -5
  9. data/README.md +2699 -0
  10. data/README.pt-br.rdoc +152 -21
  11. data/README.pt-pt.rdoc +3 -2
  12. data/README.ru.md +2724 -0
  13. data/README.zh.rdoc +3 -3
  14. data/Rakefile +3 -4
  15. data/examples/chat.rb +3 -3
  16. data/lib/sinatra/base.rb +433 -247
  17. data/lib/sinatra/main.rb +4 -2
  18. data/lib/sinatra/showexceptions.rb +6 -1
  19. data/lib/sinatra/version.rb +1 -1
  20. data/test/base_test.rb +21 -9
  21. data/test/builder_test.rb +15 -19
  22. data/test/coffee_test.rb +4 -6
  23. data/test/compile_test.rb +154 -0
  24. data/test/contest.rb +4 -6
  25. data/test/creole_test.rb +5 -5
  26. data/test/delegator_test.rb +1 -3
  27. data/test/erb_test.rb +32 -20
  28. data/test/extensions_test.rb +1 -3
  29. data/test/filter_test.rb +65 -56
  30. data/test/haml_test.rb +34 -26
  31. data/test/helpers_test.rb +331 -221
  32. data/test/integration_helper.rb +8 -0
  33. data/test/integration_test.rb +3 -1
  34. data/test/less_test.rb +10 -8
  35. data/test/liquid_test.rb +22 -4
  36. data/test/mapped_error_test.rb +122 -96
  37. data/test/markaby_test.rb +5 -5
  38. data/test/markdown_test.rb +5 -5
  39. data/test/middleware_test.rb +3 -3
  40. data/test/nokogiri_test.rb +4 -6
  41. data/test/rabl_test.rb +89 -0
  42. data/test/radius_test.rb +4 -4
  43. data/test/rdoc_test.rb +7 -7
  44. data/test/readme_test.rb +14 -30
  45. data/test/request_test.rb +15 -0
  46. data/test/response_test.rb +3 -4
  47. data/test/result_test.rb +11 -33
  48. data/test/route_added_hook_test.rb +10 -10
  49. data/test/routing_test.rb +123 -1
  50. data/test/sass_test.rb +26 -26
  51. data/test/scss_test.rb +16 -16
  52. data/test/server_test.rb +2 -2
  53. data/test/settings_test.rb +48 -4
  54. data/test/sinatra_test.rb +2 -7
  55. data/test/slim_test.rb +37 -23
  56. data/test/static_test.rb +56 -15
  57. data/test/streaming_test.rb +11 -2
  58. data/test/templates_test.rb +117 -45
  59. data/test/textile_test.rb +9 -9
  60. data/test/views/hello.rabl +2 -0
  61. data/test/views/hello.wlang +1 -0
  62. data/test/views/hello.yajl +1 -0
  63. data/test/views/layout2.rabl +3 -0
  64. data/test/views/layout2.wlang +2 -0
  65. data/test/wlang_test.rb +87 -0
  66. data/test/yajl_test.rb +86 -0
  67. metadata +27 -17
  68. data/README.de.rdoc +0 -2097
  69. data/README.fr.rdoc +0 -2036
  70. data/README.rdoc +0 -2017
  71. data/README.ru.rdoc +0 -1785
@@ -126,6 +126,14 @@ module IntegrationHelper
126
126
  name.to_s == "thin"
127
127
  end
128
128
 
129
+ def puma?
130
+ name.to_s == "puma"
131
+ end
132
+
133
+ def trinidad?
134
+ name.to_s == "trinidad"
135
+ end
136
+
129
137
  def warnings
130
138
  log.scan(%r[(?:\(eval|lib/sinatra).*warning:.*$])
131
139
  end
@@ -10,8 +10,10 @@ class IntegrationTest < Test::Unit::TestCase
10
10
  attr_accessor :server
11
11
 
12
12
  it('sets the app_file') { assert_equal server.app_file, server.get("/app_file") }
13
+ it('only extends main') { assert_equal "true", server.get("/mainonly") }
13
14
 
14
15
  it 'logs once in development mode' do
16
+ next if server.puma? or RUBY_ENGINE == 'jruby'
15
17
  random = "%064x" % Kernel.rand(2**256-1)
16
18
  server.get "/ping?x=#{random}"
17
19
  count = server.log.scan("GET /ping?x=#{random}").count
@@ -19,7 +21,7 @@ class IntegrationTest < Test::Unit::TestCase
19
21
  end
20
22
 
21
23
  it 'streams' do
22
- next if server.webrick?
24
+ next if server.webrick? or server.trinidad?
23
25
  times, chunks = [Time.now], []
24
26
  server.get_stream do |chunk|
25
27
  next if chunk.empty?
@@ -5,22 +5,26 @@ require 'less'
5
5
 
6
6
  class LessTest < Test::Unit::TestCase
7
7
  def less_app(options = {}, &block)
8
- mock_app {
8
+ mock_app do
9
9
  set :views, File.dirname(__FILE__) + '/views'
10
10
  set options
11
- get '/', &block
12
- }
11
+ get('/', &block)
12
+ end
13
13
  get '/'
14
14
  end
15
15
 
16
16
  it 'renders inline Less strings' do
17
- less_app { less "@white_color: #fff; #main { background-color: @white_color }" }
17
+ less_app {
18
+ less "@white_color: #fff; #main { background-color: @white_color }"
19
+ }
18
20
  assert ok?
19
21
  assert_equal "#main{background-color:#ffffff;}", body.gsub(/\s/, "")
20
22
  end
21
23
 
22
24
  it 'defaults content type to css' do
23
- less_app { less "@white_color: #fff; #main { background-color: @white_color }" }
25
+ less_app {
26
+ less "@white_color: #fff; #main { background-color: @white_color }"
27
+ }
24
28
  assert ok?
25
29
  assert_equal "text/css;charset=utf-8", response['Content-Type']
26
30
  end
@@ -55,9 +59,7 @@ class LessTest < Test::Unit::TestCase
55
59
  end
56
60
 
57
61
  it "raises error if template not found" do
58
- mock_app {
59
- get('/') { less :no_such_template }
60
- }
62
+ mock_app { get('/') { less :no_such_template } }
61
63
  assert_raise(Errno::ENOENT) { get('/') }
62
64
  end
63
65
  end
@@ -7,7 +7,7 @@ class LiquidTest < Test::Unit::TestCase
7
7
  def liquid_app(&block)
8
8
  mock_app do
9
9
  set :views, File.dirname(__FILE__) + '/views'
10
- get '/', &block
10
+ get('/', &block)
11
11
  end
12
12
  get '/'
13
13
  end
@@ -44,14 +44,32 @@ class LiquidTest < Test::Unit::TestCase
44
44
  mock_app { get('/') { liquid :no_such_template } }
45
45
  assert_raise(Errno::ENOENT) { get('/') }
46
46
  end
47
-
47
+
48
48
  it "allows passing locals" do
49
- liquid_app do
49
+ liquid_app {
50
50
  liquid '{{ value }}', :locals => { :value => 'foo' }
51
- end
51
+ }
52
52
  assert ok?
53
53
  assert_equal 'foo', body
54
54
  end
55
+
56
+ it "can rendere truly nested layouts by accepting a layout and a block with the contents" do
57
+ mock_app do
58
+ template(:main_outer_layout) { "<h1>Title</h1>\n{{ yield }}" }
59
+ template(:an_inner_layout) { "<h2>Subtitle</h2>\n{{ yield }}" }
60
+ template(:a_page) { "<p>Contents.</p>\n" }
61
+ get('/') do
62
+ liquid :main_outer_layout, :layout => false do
63
+ liquid :an_inner_layout do
64
+ liquid :a_page
65
+ end
66
+ end
67
+ end
68
+ end
69
+ get '/'
70
+ assert ok?
71
+ assert_body "<h1>Title</h1>\n<h2>Subtitle</h2>\n<p>Contents.</p>\n"
72
+ end
55
73
  end
56
74
 
57
75
  rescue LoadError
@@ -7,9 +7,20 @@ class FooNotFound < Sinatra::NotFound
7
7
  end
8
8
 
9
9
  class FooSpecialError < RuntimeError
10
- def code; 501 end
10
+ def http_status; 501 end
11
11
  end
12
12
 
13
+ class FooStatusOutOfRangeError < RuntimeError
14
+ def code; 4000 end
15
+ end
16
+
17
+ class FooWithCode < RuntimeError
18
+ def code; 419 end
19
+ end
20
+
21
+ class FirstError < RuntimeError; end
22
+ class SecondError < RuntimeError; end
23
+
13
24
  class MappedErrorTest < Test::Unit::TestCase
14
25
  def test_default
15
26
  assert true
@@ -17,13 +28,11 @@ class MappedErrorTest < Test::Unit::TestCase
17
28
 
18
29
  describe 'Exception Mappings' do
19
30
  it 'invokes handlers registered with ::error when raised' do
20
- mock_app {
31
+ mock_app do
21
32
  set :raise_errors, false
22
33
  error(FooError) { 'Foo!' }
23
- get '/' do
24
- raise FooError
25
- end
26
- }
34
+ get('/') { raise FooError }
35
+ end
27
36
  get '/'
28
37
  assert_equal 500, status
29
38
  assert_equal 'Foo!', body
@@ -39,13 +48,11 @@ class MappedErrorTest < Test::Unit::TestCase
39
48
  end
40
49
 
41
50
  it 'uses the Exception handler if no matching handler found' do
42
- mock_app {
51
+ mock_app do
43
52
  set :raise_errors, false
44
53
  error(Exception) { 'Exception!' }
45
- get '/' do
46
- raise FooError
47
- end
48
- }
54
+ get('/') { raise FooError }
55
+ end
49
56
 
50
57
  get '/'
51
58
  assert_equal 500, status
@@ -53,13 +60,11 @@ class MappedErrorTest < Test::Unit::TestCase
53
60
  end
54
61
 
55
62
  it 'walks down inheritance chain for errors' do
56
- mock_app {
63
+ mock_app do
57
64
  set :raise_errors, false
58
65
  error(RuntimeError) { 'Exception!' }
59
- get '/' do
60
- raise FooError
61
- end
62
- }
66
+ get('/') { raise FooError }
67
+ end
63
68
 
64
69
  get '/'
65
70
  assert_equal 500, status
@@ -67,15 +72,13 @@ class MappedErrorTest < Test::Unit::TestCase
67
72
  end
68
73
 
69
74
  it 'favors subclass handler over superclass handler if available' do
70
- mock_app {
75
+ mock_app do
71
76
  set :raise_errors, false
72
77
  error(Exception) { 'Exception!' }
73
78
  error(FooError) { 'FooError!' }
74
79
  error(RuntimeError) { 'Exception!' }
75
- get '/' do
76
- raise FooError
77
- end
78
- }
80
+ get('/') { raise FooError }
81
+ end
79
82
 
80
83
  get '/'
81
84
  assert_equal 500, status
@@ -83,68 +86,58 @@ class MappedErrorTest < Test::Unit::TestCase
83
86
  end
84
87
 
85
88
  it "sets env['sinatra.error'] to the rescued exception" do
86
- mock_app {
89
+ mock_app do
87
90
  set :raise_errors, false
88
- error(FooError) {
91
+ error(FooError) do
89
92
  assert env.include?('sinatra.error')
90
93
  assert env['sinatra.error'].kind_of?(FooError)
91
94
  'looks good'
92
- }
93
- get '/' do
94
- raise FooError
95
95
  end
96
- }
96
+ get('/') { raise FooError }
97
+ end
97
98
  get '/'
98
99
  assert_equal 'looks good', body
99
100
  end
100
101
 
101
102
  it "raises errors from the app when raise_errors set and no handler defined" do
102
- mock_app {
103
+ mock_app do
103
104
  set :raise_errors, true
104
- get '/' do
105
- raise FooError
106
- end
107
- }
105
+ get('/') { raise FooError }
106
+ end
108
107
  assert_raise(FooError) { get '/' }
109
108
  end
110
109
 
111
110
  it "calls error handlers before raising errors even when raise_errors is set" do
112
- mock_app {
111
+ mock_app do
113
112
  set :raise_errors, true
114
113
  error(FooError) { "she's there." }
115
- get '/' do
116
- raise FooError
117
- end
118
- }
114
+ get('/') { raise FooError }
115
+ end
119
116
  assert_nothing_raised { get '/' }
120
117
  assert_equal 500, status
121
118
  end
122
119
 
123
120
  it "never raises Sinatra::NotFound beyond the application" do
124
- mock_app(Sinatra::Application) { get('/') { raise Sinatra::NotFound }}
121
+ mock_app(Sinatra::Application) do
122
+ get('/') { raise Sinatra::NotFound }
123
+ end
125
124
  assert_nothing_raised { get '/' }
126
125
  assert_equal 404, status
127
126
  end
128
127
 
129
128
  it "cascades for subclasses of Sinatra::NotFound" do
130
- mock_app {
129
+ mock_app do
131
130
  set :raise_errors, true
132
131
  error(FooNotFound) { "foo! not found." }
133
- get '/' do
134
- raise FooNotFound
135
- end
136
- }
132
+ get('/') { raise FooNotFound }
133
+ end
137
134
  assert_nothing_raised { get '/' }
138
135
  assert_equal 404, status
139
136
  assert_equal 'foo! not found.', body
140
137
  end
141
138
 
142
139
  it 'has a not_found method for backwards compatibility' do
143
- mock_app {
144
- not_found do
145
- "Lost, are we?"
146
- end
147
- }
140
+ mock_app { not_found { "Lost, are we?" } }
148
141
 
149
142
  get '/test'
150
143
  assert_equal 404, status
@@ -155,12 +148,10 @@ class MappedErrorTest < Test::Unit::TestCase
155
148
  base = Class.new(Sinatra::Base)
156
149
  base.error(FooError) { 'base class' }
157
150
 
158
- mock_app(base) {
151
+ mock_app(base) do
159
152
  set :raise_errors, false
160
- get '/' do
161
- raise FooError
162
- end
163
- }
153
+ get('/') { raise FooError }
154
+ end
164
155
 
165
156
  get '/'
166
157
  assert_equal 'base class', body
@@ -170,19 +161,17 @@ class MappedErrorTest < Test::Unit::TestCase
170
161
  base = Class.new(Sinatra::Base)
171
162
  base.error(FooError) { 'base class' }
172
163
 
173
- mock_app(base) {
164
+ mock_app(base) do
174
165
  set :raise_errors, false
175
166
  error(FooError) { 'subclass' }
176
- get '/' do
177
- raise FooError
178
- end
179
- }
167
+ get('/') { raise FooError }
168
+ end
180
169
 
181
170
  get '/'
182
171
  assert_equal 'subclass', body
183
172
  end
184
173
 
185
- it 'honors Exception#code if present' do
174
+ it 'honors Exception#http_status if present' do
186
175
  mock_app do
187
176
  set :raise_errors, false
188
177
  error(501) { 'Foo!' }
@@ -192,68 +181,105 @@ class MappedErrorTest < Test::Unit::TestCase
192
181
  assert_equal 501, status
193
182
  assert_equal 'Foo!', body
194
183
  end
184
+
185
+ it 'does not use Exception#code by default' do
186
+ mock_app do
187
+ set :raise_errors, false
188
+ get('/') { raise FooWithCode }
189
+ end
190
+ get '/'
191
+ assert_equal 500, status
192
+ end
193
+
194
+ it 'uses Exception#code if use_code is enabled' do
195
+ mock_app do
196
+ set :raise_errors, false
197
+ set :use_code, true
198
+ get('/') { raise FooWithCode }
199
+ end
200
+ get '/'
201
+ assert_equal 419, status
202
+ end
203
+
204
+ it 'does not rely on Exception#code for invalid codes' do
205
+ mock_app do
206
+ set :raise_errors, false
207
+ set :use_code, true
208
+ get('/') { raise FooStatusOutOfRangeError }
209
+ end
210
+ get '/'
211
+ assert_equal 500, status
212
+ end
213
+
214
+ it "allows a stack of exception_handlers" do
215
+ mock_app do
216
+ set :raise_errors, false
217
+ error(FirstError) { 'First!' }
218
+ error(SecondError) { 'Second!' }
219
+ get('/'){ raise SecondError }
220
+ end
221
+ get '/'
222
+ assert_equal 500, status
223
+ assert_equal 'Second!', body
224
+ end
225
+
226
+ it "allows an exception handler to pass control to the next exception handler" do
227
+ mock_app do
228
+ set :raise_errors, false
229
+ error(500, FirstError) { 'First!' }
230
+ error(500, SecondError) { pass }
231
+ get('/') { raise 500 }
232
+ end
233
+ get '/'
234
+ assert_equal 500, status
235
+ assert_equal 'First!', body
236
+ end
237
+
238
+ it "allows an exception handler to handle the exception" do
239
+ mock_app do
240
+ set :raise_errors, false
241
+ error(500, FirstError) { 'First!' }
242
+ error(500, SecondError) { 'Second!' }
243
+ get('/') { raise 500 }
244
+ end
245
+ get '/'
246
+ assert_equal 500, status
247
+ assert_equal 'Second!', body
248
+ end
195
249
  end
196
250
 
197
251
  describe 'Custom Error Pages' do
198
252
  it 'allows numeric status code mappings to be registered with ::error' do
199
- mock_app {
253
+ mock_app do
200
254
  set :raise_errors, false
201
255
  error(500) { 'Foo!' }
202
- get '/' do
203
- [500, {}, 'Internal Foo Error']
204
- end
205
- }
256
+ get('/') { [500, {}, 'Internal Foo Error'] }
257
+ end
206
258
  get '/'
207
259
  assert_equal 500, status
208
260
  assert_equal 'Foo!', body
209
261
  end
210
262
 
211
263
  it 'allows ranges of status code mappings to be registered with :error' do
212
- mock_app {
264
+ mock_app do
213
265
  set :raise_errors, false
214
266
  error(500..550) { "Error: #{response.status}" }
215
- get '/' do
216
- [507, {}, 'A very special error']
217
- end
218
- }
267
+ get('/') { [507, {}, 'A very special error'] }
268
+ end
219
269
  get '/'
220
270
  assert_equal 507, status
221
271
  assert_equal 'Error: 507', body
222
272
  end
223
273
 
224
274
  it 'allows passing more than one range' do
225
- mock_app {
275
+ mock_app do
226
276
  set :raise_errors, false
227
277
  error(409..411, 503..509) { "Error: #{response.status}" }
228
- get '/' do
229
- [507, {}, 'A very special error']
230
- end
231
- }
278
+ get('/') { [507, {}, 'A very special error'] }
279
+ end
232
280
  get '/'
233
281
  assert_equal 507, status
234
282
  assert_equal 'Error: 507', body
235
283
  end
236
-
237
- class FooError < RuntimeError
238
- end
239
-
240
- it 'runs after exception mappings and overwrites body' do
241
- mock_app {
242
- set :raise_errors, false
243
- error FooError do
244
- response.status = 502
245
- 'from exception mapping'
246
- end
247
- error(500) { 'from 500 handler' }
248
- error(502) { 'from custom error page' }
249
-
250
- get '/' do
251
- raise FooError
252
- end
253
- }
254
- get '/'
255
- assert_equal 502, status
256
- assert_equal 'from custom error page', body
257
- end
258
284
  end
259
285
  end