sinatra 1.0 → 1.1.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 (57) hide show
  1. data/CHANGES +108 -1
  2. data/LICENSE +1 -1
  3. data/README.de.rdoc +1024 -0
  4. data/README.es.rdoc +1047 -0
  5. data/README.fr.rdoc +1038 -0
  6. data/README.hu.rdoc +607 -0
  7. data/README.jp.rdoc +473 -15
  8. data/README.rdoc +429 -41
  9. data/Rakefile +17 -6
  10. data/lib/sinatra/base.rb +357 -158
  11. data/lib/sinatra/showexceptions.rb +9 -1
  12. data/sinatra.gemspec +52 -9
  13. data/test/builder_test.rb +25 -1
  14. data/test/coffee_test.rb +88 -0
  15. data/test/encoding_test.rb +18 -0
  16. data/test/filter_test.rb +61 -2
  17. data/test/hello.mab +1 -0
  18. data/test/helper.rb +1 -0
  19. data/test/helpers_test.rb +141 -37
  20. data/test/less_test.rb +26 -2
  21. data/test/liquid_test.rb +58 -0
  22. data/test/markaby_test.rb +58 -0
  23. data/test/markdown_test.rb +35 -0
  24. data/test/nokogiri_test.rb +69 -0
  25. data/test/radius_test.rb +59 -0
  26. data/test/rdoc_test.rb +34 -0
  27. data/test/request_test.rb +12 -0
  28. data/test/routing_test.rb +35 -1
  29. data/test/sass_test.rb +46 -16
  30. data/test/scss_test.rb +88 -0
  31. data/test/settings_test.rb +32 -0
  32. data/test/sinatra_test.rb +4 -0
  33. data/test/static_test.rb +64 -0
  34. data/test/templates_test.rb +55 -1
  35. data/test/textile_test.rb +34 -0
  36. data/test/views/ascii.haml +2 -0
  37. data/test/views/explicitly_nested.str +1 -0
  38. data/test/views/hello.coffee +1 -0
  39. data/test/views/hello.liquid +1 -0
  40. data/test/views/hello.mab +1 -0
  41. data/test/views/hello.md +1 -0
  42. data/test/views/hello.nokogiri +1 -0
  43. data/test/views/hello.radius +1 -0
  44. data/test/views/hello.rdoc +1 -0
  45. data/test/views/hello.sass +1 -1
  46. data/test/views/hello.scss +3 -0
  47. data/test/views/hello.str +1 -0
  48. data/test/views/hello.textile +1 -0
  49. data/test/views/layout2.liquid +2 -0
  50. data/test/views/layout2.mab +2 -0
  51. data/test/views/layout2.nokogiri +3 -0
  52. data/test/views/layout2.radius +2 -0
  53. data/test/views/layout2.str +2 -0
  54. data/test/views/nested.str +1 -0
  55. data/test/views/utf8.haml +2 -0
  56. metadata +240 -33
  57. data/lib/sinatra/tilt.rb +0 -746
@@ -4,30 +4,54 @@ begin
4
4
  require 'sass'
5
5
 
6
6
  class SassTest < Test::Unit::TestCase
7
- def sass_app(&block)
7
+ def sass_app(options = {}, &block)
8
8
  mock_app {
9
9
  set :views, File.dirname(__FILE__) + '/views'
10
+ set options
10
11
  get '/', &block
11
12
  }
12
13
  get '/'
13
14
  end
14
15
 
15
16
  it 'renders inline Sass strings' do
16
- sass_app { sass "#sass\n :background-color #FFF\n" }
17
+ sass_app { sass "#sass\n :background-color white\n" }
17
18
  assert ok?
18
- assert_equal "#sass {\n background-color: #FFF; }\n", body
19
+ assert_equal "#sass {\n background-color: white; }\n", body
20
+ end
21
+
22
+ it 'defaults content type to css' do
23
+ sass_app { sass "#sass\n :background-color white\n" }
24
+ assert ok?
25
+ assert_equal "text/css;charset=utf-8", response['Content-Type']
26
+ end
27
+
28
+ it 'defaults allows setting content type per route' do
29
+ sass_app do
30
+ content_type :html
31
+ sass "#sass\n :background-color white\n"
32
+ end
33
+ assert ok?
34
+ assert_equal "text/html;charset=utf-8", response['Content-Type']
35
+ end
36
+
37
+ it 'defaults allows setting content type globally' do
38
+ sass_app(:sass => { :content_type => 'html' }) do
39
+ sass "#sass\n :background-color white\n"
40
+ end
41
+ assert ok?
42
+ assert_equal "text/html;charset=utf-8", response['Content-Type']
19
43
  end
20
44
 
21
45
  it 'renders .sass files in views path' do
22
46
  sass_app { sass :hello }
23
47
  assert ok?
24
- assert_equal "#sass {\n background-color: #FFF; }\n", body
48
+ assert_equal "#sass {\n background-color: white; }\n", body
25
49
  end
26
50
 
27
51
  it 'ignores the layout option' do
28
52
  sass_app { sass :hello, :layout => :layout2 }
29
53
  assert ok?
30
- assert_equal "#sass {\n background-color: #FFF; }\n", body
54
+ assert_equal "#sass {\n background-color: white; }\n", body
31
55
  end
32
56
 
33
57
  it "raises error if template not found" do
@@ -39,44 +63,50 @@ class SassTest < Test::Unit::TestCase
39
63
 
40
64
  it "passes SASS options to the Sass engine" do
41
65
  sass_app {
42
- sass "#sass\n :background-color #FFF\n :color #000\n", :style => :compact
66
+ sass "#sass\n :background-color white\n :color black\n",
67
+ :style => :compact
43
68
  }
44
69
  assert ok?
45
- assert_equal "#sass { background-color: #FFF; color: #000; }\n", body
70
+ assert_equal "#sass { background-color: white; color: black; }\n", body
46
71
  end
47
72
 
48
73
  it "passes default SASS options to the Sass engine" do
49
74
  mock_app {
50
75
  set :sass, {:style => :compact} # default Sass style is :nested
51
76
  get '/' do
52
- sass "#sass\n :background-color #FFF\n :color #000\n"
77
+ sass "#sass\n :background-color white\n :color black\n"
53
78
  end
54
79
  }
55
80
  get '/'
56
81
  assert ok?
57
- assert_equal "#sass { background-color: #FFF; color: #000; }\n", body
82
+ assert_equal "#sass { background-color: white; color: black; }\n", body
58
83
  end
59
84
 
60
- it "merges the default SASS options with the overrides and passes them to the Sass engine" do
85
+ it "merges the default SASS options with the overrides" do
61
86
  mock_app {
62
- set :sass, {:style => :compact, :attribute_syntax => :alternate } # default Sass attribute_syntax is :normal (with : in front)
87
+ # default Sass attribute_syntax is :normal (with : in front)
88
+ set :sass, {:style => :compact, :attribute_syntax => :alternate }
63
89
  get '/' do
64
- sass "#sass\n background-color: #FFF\n color: #000\n"
90
+ sass "#sass\n background-color: white\n color: black\n"
65
91
  end
66
92
  get '/raised' do
67
- sass "#sass\n :background-color #FFF\n :color #000\n", :style => :expanded # retains global attribute_syntax settings
93
+ # retains global attribute_syntax settings
94
+ sass "#sass\n :background-color white\n :color black\n",
95
+ :style => :expanded
68
96
  end
69
97
  get '/expanded_normal' do
70
- sass "#sass\n :background-color #FFF\n :color #000\n", :style => :expanded, :attribute_syntax => :normal
98
+ sass "#sass\n :background-color white\n :color black\n",
99
+ :style => :expanded, :attribute_syntax => :normal
71
100
  end
72
101
  }
73
102
  get '/'
74
103
  assert ok?
75
- assert_equal "#sass { background-color: #FFF; color: #000; }\n", body
104
+ assert_equal "#sass { background-color: white; color: black; }\n", body
76
105
  assert_raise(Sass::SyntaxError) { get('/raised') }
77
106
  get '/expanded_normal'
78
107
  assert ok?
79
- assert_equal "#sass {\n background-color: #FFF;\n color: #000;\n}\n", body
108
+ assert_equal "#sass {\n background-color: white;\n color: black;\n}\n",
109
+ body
80
110
  end
81
111
  end
82
112
 
@@ -0,0 +1,88 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ begin
4
+ require 'sass'
5
+
6
+ class ScssTest < Test::Unit::TestCase
7
+ def scss_app(options = {}, &block)
8
+ mock_app {
9
+ set :views, File.dirname(__FILE__) + '/views'
10
+ set options
11
+ get '/', &block
12
+ }
13
+ get '/'
14
+ end
15
+
16
+ it 'renders inline Scss strings' do
17
+ scss_app { scss "#scss {\n background-color: white; }\n" }
18
+ assert ok?
19
+ assert_equal "#scss {\n background-color: white; }\n", body
20
+ end
21
+
22
+ it 'defaults content type to css' do
23
+ scss_app { scss "#scss {\n background-color: white; }\n" }
24
+ assert ok?
25
+ assert_equal "text/css;charset=utf-8", response['Content-Type']
26
+ end
27
+
28
+ it 'defaults allows setting content type per route' do
29
+ scss_app do
30
+ content_type :html
31
+ scss "#scss {\n background-color: white; }\n"
32
+ end
33
+ assert ok?
34
+ assert_equal "text/html;charset=utf-8", response['Content-Type']
35
+ end
36
+
37
+ it 'defaults allows setting content type globally' do
38
+ scss_app(:scss => { :content_type => 'html' }) do
39
+ scss "#scss {\n background-color: white; }\n"
40
+ end
41
+ assert ok?
42
+ assert_equal "text/html;charset=utf-8", response['Content-Type']
43
+ end
44
+
45
+ it 'renders .scss files in views path' do
46
+ scss_app { scss :hello }
47
+ assert ok?
48
+ assert_equal "#scss {\n background-color: white; }\n", body
49
+ end
50
+
51
+ it 'ignores the layout option' do
52
+ scss_app { scss :hello, :layout => :layout2 }
53
+ assert ok?
54
+ assert_equal "#scss {\n background-color: white; }\n", body
55
+ end
56
+
57
+ it "raises error if template not found" do
58
+ mock_app {
59
+ get('/') { scss :no_such_template }
60
+ }
61
+ assert_raise(Errno::ENOENT) { get('/') }
62
+ end
63
+
64
+ it "passes scss options to the scss engine" do
65
+ scss_app {
66
+ scss "#scss {\n background-color: white;\n color: black\n}",
67
+ :style => :compact
68
+ }
69
+ assert ok?
70
+ assert_equal "#scss { background-color: white; color: black; }\n", body
71
+ end
72
+
73
+ it "passes default scss options to the scss engine" do
74
+ mock_app {
75
+ set :scss, {:style => :compact} # default scss style is :nested
76
+ get '/' do
77
+ scss "#scss {\n background-color: white;\n color: black;\n}"
78
+ end
79
+ }
80
+ get '/'
81
+ assert ok?
82
+ assert_equal "#scss { background-color: white; color: black; }\n", body
83
+ end
84
+ end
85
+
86
+ rescue
87
+ warn "#{$!.to_s}: skipping scss tests"
88
+ end
@@ -43,6 +43,11 @@ class SettingsTest < Test::Unit::TestCase
43
43
  assert_equal 'bizzle', @base.baz
44
44
  end
45
45
 
46
+ it 'sets multiple settings using #each' do
47
+ @base.set [["foo", "bar"]]
48
+ assert_equal "bar", @base.foo
49
+ end
50
+
46
51
  it 'inherits settings methods when subclassed' do
47
52
  @base.set :foo, 'bar'
48
53
  @base.set :biz, Proc.new { 'baz' }
@@ -110,6 +115,10 @@ class SettingsTest < Test::Unit::TestCase
110
115
  assert_equal :foo, @base.new.settings.environment
111
116
  end
112
117
 
118
+ it 'is accessible from class via #settings' do
119
+ assert_equal :foo, @base.settings.environment
120
+ end
121
+
113
122
  describe 'methodoverride' do
114
123
  it 'is disabled on Base' do
115
124
  assert ! @base.method_override?
@@ -193,6 +202,29 @@ class SettingsTest < Test::Unit::TestCase
193
202
  assert body.include?("StandardError")
194
203
  assert body.include?("<code>show_exceptions</code> setting")
195
204
  end
205
+
206
+ it 'does not override app-specified error handling when set to :after_handler' do
207
+ klass = Sinatra.new(Sinatra::Application)
208
+ mock_app(klass) {
209
+ set :show_exceptions, :after_handler
210
+
211
+ error RuntimeError do
212
+ 'Big mistake !'
213
+ end
214
+
215
+ get '/' do
216
+ raise RuntimeError
217
+ end
218
+ }
219
+
220
+ get '/'
221
+ assert_equal 500, status
222
+
223
+ assert ! body.include?("<code>")
224
+ assert body.include? "Big mistake !"
225
+
226
+ end
227
+
196
228
  end
197
229
 
198
230
  describe 'dump_errors' do
@@ -10,4 +10,8 @@ class SinatraTest < Test::Unit::TestCase
10
10
  end
11
11
  assert_same Sinatra::Base, app.superclass
12
12
  end
13
+
14
+ it "responds to #template_cache" do
15
+ assert_kind_of Tilt::Cache, Sinatra::Base.new.template_cache
16
+ end
13
17
  end
@@ -90,4 +90,68 @@ class StaticTest < Test::Unit::TestCase
90
90
  get "/../#{File.basename(__FILE__)}"
91
91
  assert not_found?
92
92
  end
93
+
94
+ def test_valid_range(http_range, range, path, file)
95
+ request = Rack::MockRequest.new(@app)
96
+ response = request.get("/#{File.basename(path)}", 'HTTP_RANGE' => http_range)
97
+
98
+ should_be = file[range]
99
+ expected_range = "bytes #{range.begin}-#{range.end}/#{file.length}"
100
+
101
+ assert_equal 206,response.status, "Should be HTTP/1.1 206 Partial content"
102
+ assert_equal should_be.length, response.body.length, "Unexpected response length for #{http_range}"
103
+ assert_equal should_be, response.body, "Unexpected response data for #{http_range}"
104
+ assert_equal should_be.length.to_s, response['Content-Length'], "Incorrect Content-Length for #{http_range}"
105
+ assert_equal expected_range, response['Content-Range'], "Incorrect Content-Range for #{http_range}"
106
+ end
107
+
108
+ it 'handles valid byte ranges correctly' do
109
+ # Use the biggest file in this dir so we can test ranges > 8k bytes. (StaticFile sends in 8k chunks.)
110
+ path = File.dirname(__FILE__) + '/helpers_test.rb' # currently 16k bytes
111
+ file = File.read(path)
112
+ length = file.length
113
+ assert length > 9000, "The test file #{path} is too short (#{length} bytes) to run these tests"
114
+
115
+ [0..0, 42..88, 1234..1234, 100..9000, 0..(length-1), (length-1)..(length-1)].each do |range|
116
+ test_valid_range("bytes=#{range.begin}-#{range.end}", range, path, file)
117
+ end
118
+
119
+ [0, 100, length-100, length-1].each do |start|
120
+ test_valid_range("bytes=#{start}-", (start..length-1), path, file)
121
+ end
122
+
123
+ [1, 100, length-100, length-1, length].each do |range_length|
124
+ test_valid_range("bytes=-#{range_length}", (length-range_length..length-1), path, file)
125
+ end
126
+
127
+ # Some valid ranges that exceed the length of the file:
128
+ test_valid_range("bytes=100-999999", (100..length-1), path, file)
129
+ test_valid_range("bytes=100-#{length}", (100..length-1), path, file)
130
+ test_valid_range("bytes=-#{length}", (0..length-1), path, file)
131
+ test_valid_range("bytes=-#{length+1}", (0..length-1), path, file)
132
+ test_valid_range("bytes=-999999", (0..length-1), path, file)
133
+ end
134
+
135
+ it 'correctly ignores syntactically invalid range requests' do
136
+ # ...and also ignores multi-range requests, which aren't supported yet
137
+ ["bytes=45-40", "bytes=IV-LXVI", "octets=10-20", "bytes=-", "bytes=1-2,3-4"].each do |http_range|
138
+ request = Rack::MockRequest.new(@app)
139
+ response = request.get("/#{File.basename(__FILE__)}", 'HTTP_RANGE' => http_range)
140
+
141
+ assert_equal 200,response.status, "Invalid range '#{http_range}' should be ignored"
142
+ assert_equal nil,response['Content-Range'], "Invalid range '#{http_range}' should be ignored"
143
+ end
144
+ end
145
+
146
+ it 'returns error 416 for unsatisfiable range requests' do
147
+ # An unsatisfiable request is one that specifies a start that's at or past the end of the file.
148
+ length = File.read(__FILE__).length
149
+ ["bytes=888888-", "bytes=888888-999999", "bytes=#{length}-#{length}"].each do |http_range|
150
+ request = Rack::MockRequest.new(@app)
151
+ response = request.get("/#{File.basename(__FILE__)}", 'HTTP_RANGE' => http_range)
152
+
153
+ assert_equal 416,response.status, "Unsatisfiable range '#{http_range}' should return 416"
154
+ assert_equal "bytes */#{length}",response['Content-Range'], "416 response should include actual length"
155
+ end
156
+ end
93
157
  end
@@ -1,4 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
+ File.delete(File.dirname(__FILE__) + '/views/layout.test') rescue nil
2
3
 
3
4
  class TestTemplate < Tilt::Template
4
5
  def prepare
@@ -14,9 +15,11 @@ class TestTemplate < Tilt::Template
14
15
  end
15
16
 
16
17
  class TemplatesTest < Test::Unit::TestCase
17
- def render_app(base=Sinatra::Base, &block)
18
+ def render_app(base=Sinatra::Base, options = {}, &block)
19
+ base, options = Sinatra::Base, base if base.is_a? Hash
18
20
  mock_app(base) {
19
21
  set :views, File.dirname(__FILE__) + '/views'
22
+ set options
20
23
  get '/', &block
21
24
  template(:layout3) { "Layout 3!\n" }
22
25
  }
@@ -77,12 +80,39 @@ class TemplatesTest < Test::Unit::TestCase
77
80
  assert_equal "Layout 3!\nHello World!\n", body
78
81
  end
79
82
 
83
+ it 'avoids wrapping layouts around nested templates' do
84
+ render_app { render :str, :nested, :layout => :layout2 }
85
+ assert ok?
86
+ assert_equal "<h1>String Layout!</h1>\n<content><h1>Hello From String</h1></content>", body
87
+ end
88
+
89
+ it 'allows explicitly wrapping layouts around nested templates' do
90
+ render_app { render :str, :explicitly_nested, :layout => :layout2 }
91
+ assert ok?
92
+ assert_equal "<h1>String Layout!</h1>\n<content><h1>String Layout!</h1>\n<h1>Hello From String</h1></content>", body
93
+ end
94
+
95
+ it 'two independent render calls do not disable layouts' do
96
+ render_app do
97
+ render :str, :explicitly_nested, :layout => :layout2
98
+ render :str, :nested, :layout => :layout2
99
+ end
100
+ assert ok?
101
+ assert_equal "<h1>String Layout!</h1>\n<content><h1>Hello From String</h1></content>", body
102
+ end
103
+
80
104
  it 'loads templates from source file' do
81
105
  mock_app { enable :inline_templates }
82
106
  assert_equal "this is foo\n\n", @app.templates[:foo][0]
83
107
  assert_equal "X\n= yield\nX\n", @app.templates[:layout][0]
84
108
  end
85
109
 
110
+ it 'ignores spaces after names of inline templates' do
111
+ mock_app { enable :inline_templates }
112
+ assert_equal "There's a space after 'bar'!\n\n", @app.templates[:bar][0]
113
+ assert_equal "this is not foo\n\n", @app.templates[:"foo bar"][0]
114
+ end
115
+
86
116
  it 'loads templates from given source file' do
87
117
  mock_app { set :inline_templates, __FILE__ }
88
118
  assert_equal "this is foo\n\n", @app.templates[:foo][0]
@@ -128,6 +158,24 @@ class TemplatesTest < Test::Unit::TestCase
128
158
  assert_equal 'bar', body
129
159
  end
130
160
 
161
+ it 'allows setting default content type per template engine' do
162
+ render_app(:str => { :content_type => :txt }) { render :str, 'foo' }
163
+ assert_equal 'text/plain;charset=utf-8', response['Content-Type']
164
+ end
165
+
166
+ it 'setting default content type does not affect other template engines' do
167
+ render_app(:str => { :content_type => :txt }) { render :test, 'foo' }
168
+ assert_equal 'text/html;charset=utf-8', response['Content-Type']
169
+ end
170
+
171
+ it 'setting default content type per template engine does not override content_type' do
172
+ render_app :str => { :content_type => :txt } do
173
+ content_type :html
174
+ render :str, 'foo'
175
+ end
176
+ assert_equal 'text/html;charset=utf-8', response['Content-Type']
177
+ end
178
+
131
179
  it 'uses templates in superclasses before subclasses' do
132
180
  base = Class.new(Sinatra::Base)
133
181
  base.template(:foo) { 'template in superclass' }
@@ -153,6 +201,12 @@ __END__
153
201
  @@ foo
154
202
  this is foo
155
203
 
204
+ @@ bar
205
+ There's a space after 'bar'!
206
+
207
+ @@ foo bar
208
+ this is not foo
209
+
156
210
  @@ layout
157
211
  X
158
212
  = yield
@@ -0,0 +1,34 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ begin
4
+ require 'redcloth'
5
+
6
+ class TextileTest < Test::Unit::TestCase
7
+ def textile_app(&block)
8
+ mock_app do
9
+ set :views, File.dirname(__FILE__) + '/views'
10
+ get '/', &block
11
+ end
12
+ get '/'
13
+ end
14
+
15
+ it 'renders inline textile strings' do
16
+ textile_app { textile 'h1. Hiya' }
17
+ assert ok?
18
+ assert_equal "<h1>Hiya</h1>", body
19
+ end
20
+
21
+ it 'renders .textile files in views path' do
22
+ textile_app { textile :hello }
23
+ assert ok?
24
+ assert_equal "<h1>Hello From Textile</h1>", body
25
+ end
26
+
27
+ it "raises error if template not found" do
28
+ mock_app { get('/') { textile :no_such_template } }
29
+ assert_raise(Errno::ENOENT) { get('/') }
30
+ end
31
+ end
32
+ rescue
33
+ warn "#{$!.to_s}: skipping textile tests"
34
+ end