sinatra 0.9.1.1 → 0.9.2
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.
- data/CHANGES +81 -0
- data/LICENSE +1 -1
- data/README.rdoc +63 -23
- data/Rakefile +25 -23
- data/compat/haml_test.rb +7 -4
- data/compat/helper.rb +3 -0
- data/compat/sass_test.rb +10 -0
- data/lib/sinatra/base.rb +240 -148
- data/lib/sinatra/compat.rb +16 -0
- data/lib/sinatra/main.rb +2 -14
- data/lib/sinatra/showexceptions.rb +303 -0
- data/lib/sinatra/test.rb +2 -0
- data/sinatra.gemspec +13 -4
- data/test/base_test.rb +123 -93
- data/test/builder_test.rb +2 -1
- data/test/contest.rb +64 -0
- data/test/erb_test.rb +1 -1
- data/test/extensions_test.rb +17 -1
- data/test/filter_test.rb +1 -1
- data/test/haml_test.rb +25 -3
- data/test/helper.rb +43 -48
- data/test/helpers_test.rb +446 -440
- data/test/mapped_error_test.rb +138 -143
- data/test/middleware_test.rb +2 -2
- data/test/options_test.rb +241 -248
- data/test/render_backtrace_test.rb +145 -0
- data/test/request_test.rb +1 -1
- data/test/response_test.rb +2 -2
- data/test/result_test.rb +1 -1
- data/test/route_added_hook_test.rb +59 -0
- data/test/routing_test.rb +94 -22
- data/test/sass_test.rb +44 -1
- data/test/server_test.rb +5 -3
- data/test/sinatra_test.rb +1 -1
- data/test/static_test.rb +2 -2
- data/test/templates_test.rb +16 -4
- data/test/test_test.rb +15 -7
- data/test/views/error.builder +3 -0
- data/test/views/error.erb +3 -0
- data/test/views/error.haml +3 -0
- data/test/views/error.sass +2 -0
- metadata +32 -4
- data/test/reload_test.rb +0 -68
@@ -0,0 +1,145 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
require 'sass/error'
|
4
|
+
|
5
|
+
class RenderBacktraceTest < Test::Unit::TestCase
|
6
|
+
VIEWS = File.dirname(__FILE__) + '/views'
|
7
|
+
|
8
|
+
def assert_raise_at(filename, line, exception = RuntimeError)
|
9
|
+
f, l = nil
|
10
|
+
assert_raise(exception) do
|
11
|
+
begin
|
12
|
+
get('/')
|
13
|
+
rescue => e
|
14
|
+
f, l = e.backtrace.first.split(':')
|
15
|
+
raise
|
16
|
+
end
|
17
|
+
end
|
18
|
+
assert_equal(filename, f, "expected #{exception.name} in #{filename}, was #{f}")
|
19
|
+
assert_equal(line, l.to_i, "expected #{exception.name} in #{filename} at line #{line}, was at line #{l}")
|
20
|
+
end
|
21
|
+
|
22
|
+
def backtrace_app(&block)
|
23
|
+
mock_app {
|
24
|
+
use_in_file_templates!
|
25
|
+
set :views, RenderBacktraceTest::VIEWS
|
26
|
+
template :builder_template do
|
27
|
+
'raise "error"'
|
28
|
+
end
|
29
|
+
template :erb_template do
|
30
|
+
'<% raise "error" %>'
|
31
|
+
end
|
32
|
+
template :haml_template do
|
33
|
+
'%h1= raise "error"'
|
34
|
+
end
|
35
|
+
template :sass_template do
|
36
|
+
'+syntax-error'
|
37
|
+
end
|
38
|
+
get '/', &block
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
it "provides backtrace for Builder template" do
|
43
|
+
backtrace_app { builder :error }
|
44
|
+
assert_raise_at(File.join(VIEWS,'error.builder'), 2)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "provides backtrace for ERB template" do
|
48
|
+
backtrace_app { erb :error }
|
49
|
+
assert_raise_at(File.join(VIEWS,'error.erb'), 2)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "provides backtrace for HAML template" do
|
53
|
+
backtrace_app { haml :error }
|
54
|
+
assert_raise_at(File.join(VIEWS,'error.haml'), 2)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "provides backtrace for Sass template" do
|
58
|
+
backtrace_app { sass :error }
|
59
|
+
assert_raise_at(File.join(VIEWS,'error.sass'), 2, Sass::SyntaxError)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "provides backtrace for ERB template with locals" do
|
63
|
+
backtrace_app { erb :error, {}, :french => true }
|
64
|
+
assert_raise_at(File.join(VIEWS,'error.erb'), 3)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "provides backtrace for HAML template with locals" do
|
68
|
+
backtrace_app { haml :error, {}, :french => true }
|
69
|
+
assert_raise_at(File.join(VIEWS,'error.haml'), 3)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "provides backtrace for inline Builder string" do
|
73
|
+
backtrace_app { builder "raise 'Ack! Thbbbt!'"}
|
74
|
+
assert_raise_at(__FILE__, (__LINE__-1))
|
75
|
+
end
|
76
|
+
|
77
|
+
it "provides backtrace for inline ERB string" do
|
78
|
+
backtrace_app { erb "<% raise 'bidi-bidi-bidi' %>" }
|
79
|
+
assert_raise_at(__FILE__, (__LINE__-1))
|
80
|
+
end
|
81
|
+
|
82
|
+
it "provides backtrace for inline HAML string" do
|
83
|
+
backtrace_app { haml "%h1= raise 'Lions and tigers and bears! Oh, my!'" }
|
84
|
+
assert_raise_at(__FILE__, (__LINE__-1))
|
85
|
+
end
|
86
|
+
|
87
|
+
# it "provides backtrace for inline Sass string" do
|
88
|
+
# backtrace_app { sass '+buh-bye' }
|
89
|
+
# assert_raise_at(__FILE__, (__LINE__-1), Sass::SyntaxError)
|
90
|
+
# end
|
91
|
+
|
92
|
+
it "provides backtrace for named Builder template" do
|
93
|
+
backtrace_app { builder :builder_template }
|
94
|
+
assert_raise_at(__FILE__, (__LINE__-68))
|
95
|
+
end
|
96
|
+
|
97
|
+
it "provides backtrace for named ERB template" do
|
98
|
+
backtrace_app { erb :erb_template }
|
99
|
+
assert_raise_at(__FILE__, (__LINE__-70))
|
100
|
+
end
|
101
|
+
|
102
|
+
it "provides backtrace for named HAML template" do
|
103
|
+
backtrace_app { haml :haml_template }
|
104
|
+
assert_raise_at(__FILE__, (__LINE__-72))
|
105
|
+
end
|
106
|
+
|
107
|
+
# it "provides backtrace for named Sass template" do
|
108
|
+
# backtrace_app { sass :sass_template }
|
109
|
+
# assert_raise_at(__FILE__, (__LINE__-74), Sass::SyntaxError)
|
110
|
+
# end
|
111
|
+
|
112
|
+
it "provides backtrace for in file Builder template" do
|
113
|
+
backtrace_app { builder :builder_in_file }
|
114
|
+
assert_raise_at(__FILE__, (__LINE__+22))
|
115
|
+
end
|
116
|
+
|
117
|
+
it "provides backtrace for in file ERB template" do
|
118
|
+
backtrace_app { erb :erb_in_file }
|
119
|
+
assert_raise_at(__FILE__, (__LINE__+20))
|
120
|
+
end
|
121
|
+
|
122
|
+
it "provides backtrace for in file HAML template" do
|
123
|
+
backtrace_app { haml :haml_in_file }
|
124
|
+
assert_raise_at(__FILE__, (__LINE__+18))
|
125
|
+
end
|
126
|
+
|
127
|
+
# it "provides backtrace for in file Sass template" do
|
128
|
+
# backtrace_app { sass :sass_in_file }
|
129
|
+
# assert_raise_at(__FILE__, (__LINE__+16), Sass::SyntaxError)
|
130
|
+
# end
|
131
|
+
end
|
132
|
+
|
133
|
+
__END__
|
134
|
+
|
135
|
+
@@ builder_in_file
|
136
|
+
raise "bif"
|
137
|
+
|
138
|
+
@@ erb_in_file
|
139
|
+
<% raise "bam" %>
|
140
|
+
|
141
|
+
@@ haml_in_file
|
142
|
+
%h1= raise "pow"
|
143
|
+
|
144
|
+
@@ sass_in_file
|
145
|
+
+blam
|
data/test/request_test.rb
CHANGED
data/test/response_test.rb
CHANGED
data/test/result_test.rb
CHANGED
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
module RouteAddedTest
|
4
|
+
@routes, @procs = [], []
|
5
|
+
def self.routes ; @routes ; end
|
6
|
+
def self.procs ; @procs ; end
|
7
|
+
def self.route_added(verb, path, proc)
|
8
|
+
@routes << [verb, path]
|
9
|
+
@procs << proc
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class RouteAddedHookTest < Test::Unit::TestCase
|
14
|
+
setup {
|
15
|
+
RouteAddedTest.routes.clear
|
16
|
+
RouteAddedTest.procs.clear
|
17
|
+
}
|
18
|
+
|
19
|
+
it "should be notified of an added route" do
|
20
|
+
mock_app(Class.new(Sinatra::Base)) {
|
21
|
+
register RouteAddedTest
|
22
|
+
get('/') {}
|
23
|
+
}
|
24
|
+
|
25
|
+
assert_equal [["GET", "/"], ["HEAD", "/"]],
|
26
|
+
RouteAddedTest.routes
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should include hooks from superclass" do
|
30
|
+
a = Class.new(Class.new(Sinatra::Base))
|
31
|
+
b = Class.new(a)
|
32
|
+
|
33
|
+
a.register RouteAddedTest
|
34
|
+
b.class_eval { post("/sub_app_route") {} }
|
35
|
+
|
36
|
+
assert_equal [["POST", "/sub_app_route"]],
|
37
|
+
RouteAddedTest.routes
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should only run once per extension" do
|
41
|
+
mock_app(Class.new(Sinatra::Base)) {
|
42
|
+
register RouteAddedTest
|
43
|
+
register RouteAddedTest
|
44
|
+
get('/') {}
|
45
|
+
}
|
46
|
+
|
47
|
+
assert_equal [["GET", "/"], ["HEAD", "/"]],
|
48
|
+
RouteAddedTest.routes
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should pass route blocks as an argument" do
|
52
|
+
mock_app(Class.new(Sinatra::Base)) {
|
53
|
+
register RouteAddedTest
|
54
|
+
get('/') {}
|
55
|
+
}
|
56
|
+
|
57
|
+
assert_kind_of Proc, RouteAddedTest.procs.first
|
58
|
+
end
|
59
|
+
end
|
data/test/routing_test.rb
CHANGED
@@ -5,7 +5,23 @@ def route_def(pattern)
|
|
5
5
|
mock_app { get(pattern) { } }
|
6
6
|
end
|
7
7
|
|
8
|
-
|
8
|
+
class RegexpLookAlike
|
9
|
+
class MatchData
|
10
|
+
def captures
|
11
|
+
["this", "is", "a", "test"]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def match(string)
|
16
|
+
::RegexpLookAlike::MatchData.new if string == "/this/is/a/test/"
|
17
|
+
end
|
18
|
+
|
19
|
+
def keys
|
20
|
+
["one", "two", "three", "four"]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class RoutingTest < Test::Unit::TestCase
|
9
25
|
%w[get put post delete].each do |verb|
|
10
26
|
it "defines #{verb.upcase} request handlers with #{verb}" do
|
11
27
|
mock_app {
|
@@ -44,6 +60,21 @@ describe "Routing" do
|
|
44
60
|
assert_equal 404, status
|
45
61
|
end
|
46
62
|
|
63
|
+
it "overrides the content-type in error handlers" do
|
64
|
+
mock_app {
|
65
|
+
before { content_type 'text/plain' }
|
66
|
+
error Sinatra::NotFound do
|
67
|
+
content_type "text/html"
|
68
|
+
"<h1>Not Found</h1>"
|
69
|
+
end
|
70
|
+
}
|
71
|
+
|
72
|
+
get '/foo'
|
73
|
+
assert_equal 404, status
|
74
|
+
assert_equal 'text/html', response["Content-Type"]
|
75
|
+
assert_equal "<h1>Not Found</h1>", response.body
|
76
|
+
end
|
77
|
+
|
47
78
|
it 'takes multiple definitions of a route' do
|
48
79
|
mock_app {
|
49
80
|
user_agent(/Foo/)
|
@@ -243,17 +274,7 @@ describe "Routing" do
|
|
243
274
|
end
|
244
275
|
|
245
276
|
it "supports deeply nested params" do
|
246
|
-
|
247
|
-
'browser[chrome][engine][name]' => 'V8',
|
248
|
-
'browser[chrome][engine][version]' => '1.0',
|
249
|
-
'browser[firefox][engine][name]' => 'spidermonkey',
|
250
|
-
'browser[firefox][engine][version]' => '1.7.0',
|
251
|
-
'emacs[map][goto-line]' => 'M-g g',
|
252
|
-
'emacs[version]' => '22.3.1',
|
253
|
-
'paste[name]' => 'hello world',
|
254
|
-
'paste[syntax]' => 'ruby'
|
255
|
-
}
|
256
|
-
expected = {
|
277
|
+
expected_params = {
|
257
278
|
"emacs" => {
|
258
279
|
"map" => { "goto-line" => "M-g g" },
|
259
280
|
"version" => "22.3.1"
|
@@ -266,11 +287,11 @@ describe "Routing" do
|
|
266
287
|
}
|
267
288
|
mock_app {
|
268
289
|
get '/foo' do
|
269
|
-
assert_equal
|
290
|
+
assert_equal expected_params, params
|
270
291
|
'looks good'
|
271
292
|
end
|
272
293
|
}
|
273
|
-
get
|
294
|
+
get '/foo', expected_params
|
274
295
|
assert ok?
|
275
296
|
assert_equal 'looks good', body
|
276
297
|
end
|
@@ -352,9 +373,26 @@ describe "Routing" do
|
|
352
373
|
assert_equal 'right on', body
|
353
374
|
end
|
354
375
|
|
376
|
+
it 'supports regular expression look-alike routes' do
|
377
|
+
mock_app {
|
378
|
+
get(RegexpLookAlike.new) do
|
379
|
+
assert_equal 'this', params[:one]
|
380
|
+
assert_equal 'is', params[:two]
|
381
|
+
assert_equal 'a', params[:three]
|
382
|
+
assert_equal 'test', params[:four]
|
383
|
+
'right on'
|
384
|
+
end
|
385
|
+
}
|
386
|
+
|
387
|
+
get '/this/is/a/test/'
|
388
|
+
assert ok?
|
389
|
+
assert_equal 'right on', body
|
390
|
+
end
|
391
|
+
|
355
392
|
it 'raises a TypeError when pattern is not a String or Regexp' do
|
356
|
-
|
357
|
-
|
393
|
+
assert_raise(TypeError) {
|
394
|
+
mock_app { get(42){} }
|
395
|
+
}
|
358
396
|
end
|
359
397
|
|
360
398
|
it "returns response immediately on halt" do
|
@@ -479,7 +517,7 @@ describe "Routing" do
|
|
479
517
|
get '/foo'
|
480
518
|
assert not_found?
|
481
519
|
|
482
|
-
get '/foo',
|
520
|
+
get '/foo', {}, { 'HTTP_HOST' => 'example.com' }
|
483
521
|
assert_equal 200, status
|
484
522
|
assert_equal 'Hello World', body
|
485
523
|
end
|
@@ -494,7 +532,7 @@ describe "Routing" do
|
|
494
532
|
get '/foo'
|
495
533
|
assert not_found?
|
496
534
|
|
497
|
-
get '/foo',
|
535
|
+
get '/foo', {}, { 'HTTP_USER_AGENT' => 'Foo Bar' }
|
498
536
|
assert_equal 200, status
|
499
537
|
assert_equal 'Hello World', body
|
500
538
|
end
|
@@ -506,7 +544,7 @@ describe "Routing" do
|
|
506
544
|
'Hello ' + params[:agent].first
|
507
545
|
end
|
508
546
|
}
|
509
|
-
get '/foo',
|
547
|
+
get '/foo', {}, { 'HTTP_USER_AGENT' => 'Foo Bar' }
|
510
548
|
assert_equal 200, status
|
511
549
|
assert_equal 'Hello Bar', body
|
512
550
|
end
|
@@ -518,12 +556,12 @@ describe "Routing" do
|
|
518
556
|
end
|
519
557
|
}
|
520
558
|
|
521
|
-
get '/',
|
559
|
+
get '/', {}, { 'HTTP_ACCEPT' => 'application/xml' }
|
522
560
|
assert ok?
|
523
561
|
assert_equal 'application/xml', body
|
524
562
|
assert_equal 'application/xml', response.headers['Content-Type']
|
525
563
|
|
526
|
-
get '/',
|
564
|
+
get '/', {}, { :accept => 'text/html' }
|
527
565
|
assert !ok?
|
528
566
|
end
|
529
567
|
|
@@ -537,7 +575,7 @@ describe "Routing" do
|
|
537
575
|
}
|
538
576
|
|
539
577
|
types.each do |type|
|
540
|
-
get '/',
|
578
|
+
get '/', {}, { 'HTTP_ACCEPT' => type }
|
541
579
|
assert ok?
|
542
580
|
assert_equal type, body
|
543
581
|
assert_equal type, response.headers['Content-Type']
|
@@ -655,6 +693,40 @@ describe "Routing" do
|
|
655
693
|
assert_equal 'ab', body
|
656
694
|
end
|
657
695
|
|
696
|
+
it 'allows custom route-conditions to be set via route options' do
|
697
|
+
protector = Module.new {
|
698
|
+
def protect(*args)
|
699
|
+
condition {
|
700
|
+
unless authorize(params["user"], params["password"])
|
701
|
+
halt 403, "go away"
|
702
|
+
end
|
703
|
+
}
|
704
|
+
end
|
705
|
+
}
|
706
|
+
|
707
|
+
mock_app {
|
708
|
+
register protector
|
709
|
+
|
710
|
+
helpers do
|
711
|
+
def authorize(username, password)
|
712
|
+
username == "foo" && password == "bar"
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
716
|
+
get "/", :protect => true do
|
717
|
+
"hey"
|
718
|
+
end
|
719
|
+
}
|
720
|
+
|
721
|
+
get "/"
|
722
|
+
assert forbidden?
|
723
|
+
assert_equal "go away", body
|
724
|
+
|
725
|
+
get "/", :user => "foo", :password => "bar"
|
726
|
+
assert ok?
|
727
|
+
assert_equal "hey", body
|
728
|
+
end
|
729
|
+
|
658
730
|
# NOTE Block params behaves differently under 1.8 and 1.9. Under 1.8, block
|
659
731
|
# param arity is lax: declaring a mismatched number of block params results
|
660
732
|
# in a warning. Under 1.9, block param arity is strict: mismatched block
|
data/test/sass_test.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/helper'
|
2
|
+
require 'sass'
|
2
3
|
|
3
|
-
|
4
|
+
class SassTest < Test::Unit::TestCase
|
4
5
|
def sass_app(&block)
|
5
6
|
mock_app {
|
6
7
|
set :views, File.dirname(__FILE__) + '/views'
|
@@ -33,4 +34,46 @@ describe "Sass Templates" do
|
|
33
34
|
}
|
34
35
|
assert_raise(Errno::ENOENT) { get('/') }
|
35
36
|
end
|
37
|
+
|
38
|
+
it "passes SASS options to the Sass engine" do
|
39
|
+
sass_app {
|
40
|
+
sass "#sass\n :background-color #FFF\n :color #000\n", :style => :compact
|
41
|
+
}
|
42
|
+
assert ok?
|
43
|
+
assert_equal "#sass { background-color: #FFF; color: #000; }\n", body
|
44
|
+
end
|
45
|
+
|
46
|
+
it "passes default SASS options to the Sass engine" do
|
47
|
+
mock_app {
|
48
|
+
set :sass, {:style => :compact} # default Sass style is :nested
|
49
|
+
get '/' do
|
50
|
+
sass "#sass\n :background-color #FFF\n :color #000\n"
|
51
|
+
end
|
52
|
+
}
|
53
|
+
get '/'
|
54
|
+
assert ok?
|
55
|
+
assert_equal "#sass { background-color: #FFF; color: #000; }\n", body
|
56
|
+
end
|
57
|
+
|
58
|
+
it "merges the default SASS options with the overrides and passes them to the Sass engine" do
|
59
|
+
mock_app {
|
60
|
+
set :sass, {:style => :compact, :attribute_syntax => :alternate } # default Sass attribute_syntax is :normal (with : in front)
|
61
|
+
get '/' do
|
62
|
+
sass "#sass\n background-color: #FFF\n color: #000\n"
|
63
|
+
end
|
64
|
+
get '/raised' do
|
65
|
+
sass "#sass\n :background-color #FFF\n :color #000\n", :style => :expanded # retains global attribute_syntax settings
|
66
|
+
end
|
67
|
+
get '/expanded_normal' do
|
68
|
+
sass "#sass\n :background-color #FFF\n :color #000\n", :style => :expanded, :attribute_syntax => :normal
|
69
|
+
end
|
70
|
+
}
|
71
|
+
get '/'
|
72
|
+
assert ok?
|
73
|
+
assert_equal "#sass { background-color: #FFF; color: #000; }\n", body
|
74
|
+
assert_raise(Sass::SyntaxError) { get('/raised') }
|
75
|
+
get '/expanded_normal'
|
76
|
+
assert ok?
|
77
|
+
assert_equal "#sass {\n background-color: #FFF;\n color: #000;\n}\n", body
|
78
|
+
end
|
36
79
|
end
|