Syd-sinatra 0.3.2 → 0.9.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/AUTHORS +40 -0
  2. data/CHANGES +189 -0
  3. data/README.rdoc +148 -119
  4. data/Rakefile +34 -10
  5. data/{test → compat}/app_test.rb +11 -10
  6. data/{test → compat}/application_test.rb +21 -5
  7. data/compat/builder_test.rb +101 -0
  8. data/compat/erb_test.rb +136 -0
  9. data/{test → compat}/events_test.rb +16 -3
  10. data/compat/filter_test.rb +30 -0
  11. data/compat/haml_test.rb +233 -0
  12. data/compat/helper.rb +30 -0
  13. data/compat/mapped_error_test.rb +72 -0
  14. data/{test → compat}/pipeline_test.rb +9 -4
  15. data/compat/sass_test.rb +57 -0
  16. data/{test → compat}/streaming_test.rb +4 -1
  17. data/lib/sinatra/base.rb +843 -0
  18. data/lib/sinatra/compat.rb +239 -0
  19. data/lib/sinatra/main.rb +48 -0
  20. data/lib/sinatra/test/bacon.rb +17 -0
  21. data/lib/sinatra/test/rspec.rb +7 -8
  22. data/lib/sinatra/test/spec.rb +3 -4
  23. data/lib/sinatra/test/unit.rb +3 -5
  24. data/lib/sinatra/test.rb +114 -0
  25. data/lib/sinatra.rb +6 -1468
  26. data/sinatra.gemspec +68 -35
  27. data/test/base_test.rb +68 -0
  28. data/test/builder_test.rb +50 -87
  29. data/test/data/reload_app_file.rb +3 -0
  30. data/test/erb_test.rb +38 -124
  31. data/test/filter_test.rb +65 -20
  32. data/test/haml_test.rb +51 -216
  33. data/test/helper.rb +23 -5
  34. data/test/helpers_test.rb +361 -0
  35. data/test/mapped_error_test.rb +137 -49
  36. data/test/middleware_test.rb +58 -0
  37. data/test/options_test.rb +97 -0
  38. data/test/reload_test.rb +61 -0
  39. data/test/request_test.rb +18 -0
  40. data/test/result_test.rb +88 -0
  41. data/test/routing_test.rb +391 -0
  42. data/test/sass_test.rb +27 -48
  43. data/test/sinatra_test.rb +13 -0
  44. data/test/static_test.rb +57 -0
  45. data/test/templates_test.rb +88 -0
  46. data/test/views/hello.builder +1 -0
  47. data/test/views/hello.erb +1 -0
  48. data/test/views/hello.haml +1 -0
  49. data/test/views/hello.sass +2 -0
  50. data/test/views/hello.test +1 -0
  51. data/test/views/layout2.builder +3 -0
  52. data/test/views/layout2.erb +2 -0
  53. data/test/views/layout2.haml +2 -0
  54. data/test/views/layout2.test +1 -0
  55. metadata +79 -47
  56. data/ChangeLog +0 -78
  57. data/lib/sinatra/test/methods.rb +0 -76
  58. data/test/event_context_test.rb +0 -15
  59. /data/{test → compat}/custom_error_test.rb +0 -0
  60. /data/{test → compat}/public/foo.xml +0 -0
  61. /data/{test → compat}/sessions_test.rb +0 -0
  62. /data/{test → compat}/sym_params_test.rb +0 -0
  63. /data/{test → compat}/template_test.rb +0 -0
  64. /data/{test → compat}/use_in_file_templates_test.rb +0 -0
  65. /data/{test → compat}/views/foo.builder +0 -0
  66. /data/{test → compat}/views/foo.erb +0 -0
  67. /data/{test → compat}/views/foo.haml +0 -0
  68. /data/{test → compat}/views/foo.sass +0 -0
  69. /data/{test → compat}/views/foo_layout.erb +0 -0
  70. /data/{test → compat}/views/foo_layout.haml +0 -0
  71. /data/{test → compat}/views/layout_test/foo.builder +0 -0
  72. /data/{test → compat}/views/layout_test/foo.erb +0 -0
  73. /data/{test → compat}/views/layout_test/foo.haml +0 -0
  74. /data/{test → compat}/views/layout_test/foo.sass +0 -0
  75. /data/{test → compat}/views/layout_test/layout.builder +0 -0
  76. /data/{test → compat}/views/layout_test/layout.erb +0 -0
  77. /data/{test → compat}/views/layout_test/layout.haml +0 -0
  78. /data/{test → compat}/views/layout_test/layout.sass +0 -0
  79. /data/{test → compat}/views/no_layout/no_layout.builder +0 -0
  80. /data/{test → compat}/views/no_layout/no_layout.haml +0 -0
  81. /data/{images → lib/sinatra/images}/404.png +0 -0
  82. /data/{images → lib/sinatra/images}/500.png +0 -0
@@ -1,72 +1,160 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
- class FooError < RuntimeError; end
4
-
5
- context "Mapped errors" do
6
-
7
- setup do
8
- Sinatra.application = nil
9
- Sinatra.application.options.raise_errors = false
3
+ describe 'Exception Mappings' do
4
+ class FooError < RuntimeError
10
5
  end
11
6
 
12
- specify "are rescued and run in context" do
13
-
14
- error FooError do
15
- 'MAPPED ERROR!'
16
- end
17
-
18
- get '/' do
19
- raise FooError
20
- end
21
-
22
- get_it '/'
23
-
24
- should.be.server_error
25
- body.should.equal 'MAPPED ERROR!'
26
-
7
+ it 'invokes handlers registered with ::error when raised' do
8
+ mock_app {
9
+ set :raise_errors, false
10
+ error(FooError) { 'Foo!' }
11
+ get '/' do
12
+ raise FooError
13
+ end
14
+ }
15
+ get '/'
16
+ assert_equal 500, status
17
+ assert_equal 'Foo!', body
27
18
  end
28
19
 
29
- specify "renders empty if no each method on result" do
20
+ it 'uses the Exception handler if no matching handler found' do
21
+ mock_app {
22
+ set :raise_errors, false
23
+ error(Exception) { 'Exception!' }
24
+ get '/' do
25
+ raise FooError
26
+ end
27
+ }
28
+ get '/'
29
+ assert_equal 500, status
30
+ assert_equal 'Exception!', body
31
+ end
30
32
 
31
- error FooError do
32
- nil
33
- end
33
+ it "sets env['sinatra.error'] to the rescued exception" do
34
+ mock_app {
35
+ set :raise_errors, false
36
+ error(FooError) {
37
+ assert env.include?('sinatra.error')
38
+ assert env['sinatra.error'].kind_of?(FooError)
39
+ 'looks good'
40
+ }
41
+ get '/' do
42
+ raise FooError
43
+ end
44
+ }
45
+ get '/'
46
+ assert_equal 'looks good', body
47
+ end
34
48
 
35
- get '/' do
36
- raise FooError
37
- end
49
+ it 'dumps errors to rack.errors when dump_errors is enabled' do
50
+ mock_app {
51
+ set :raise_errors, false
52
+ set :dump_errors, true
53
+ get('/') { raise FooError, 'BOOM!' }
54
+ }
38
55
 
39
- get_it '/'
56
+ get '/'
57
+ assert_equal 500, status
58
+ assert @response.errors =~ /FooError - BOOM!:/
59
+ end
40
60
 
41
- should.be.server_error
42
- body.should.be.empty
61
+ it "raises without calling the handler when the raise_errors options is set" do
62
+ mock_app {
63
+ set :raise_errors, true
64
+ error(FooError) { "she's not there." }
65
+ get '/' do
66
+ raise FooError
67
+ end
68
+ }
69
+ assert_raise(FooError) { get '/' }
70
+ end
43
71
 
72
+ it "never raises Sinatra::NotFound beyond the application" do
73
+ mock_app {
74
+ set :raise_errors, true
75
+ get '/' do
76
+ raise Sinatra::NotFound
77
+ end
78
+ }
79
+ assert_nothing_raised { get '/' }
80
+ assert_equal 404, status
44
81
  end
45
82
 
46
- specify "doesn't override status if set" do
83
+ class FooNotFound < Sinatra::NotFound
84
+ end
47
85
 
48
- error FooError do
49
- status(200)
50
- end
86
+ it "cascades for subclasses of Sinatra::NotFound" do
87
+ mock_app {
88
+ set :raise_errors, true
89
+ error(FooNotFound) { "foo! not found." }
90
+ get '/' do
91
+ raise FooNotFound
92
+ end
93
+ }
94
+ assert_nothing_raised { get '/' }
95
+ assert_equal 404, status
96
+ assert_equal 'foo! not found.', body
97
+ end
51
98
 
52
- get '/' do
53
- raise FooError
54
- end
99
+ it 'has a not_found method for backwards compatibility' do
100
+ mock_app {
101
+ not_found do
102
+ "Lost, are we?"
103
+ end
104
+ }
55
105
 
56
- get_it '/'
106
+ get '/test'
107
+ assert_equal 404, status
108
+ assert_equal "Lost, are we?", body
109
+ end
110
+ end
57
111
 
58
- should.be.ok
112
+ describe 'Custom Error Pages' do
113
+ it 'allows numeric status code mappings to be registered with ::error' do
114
+ mock_app {
115
+ set :raise_errors, false
116
+ error(500) { 'Foo!' }
117
+ get '/' do
118
+ [500, {}, 'Internal Foo Error']
119
+ end
120
+ }
121
+ get '/'
122
+ assert_equal 500, status
123
+ assert_equal 'Foo!', body
124
+ end
59
125
 
126
+ it 'allows ranges of status code mappings to be registered with :error' do
127
+ mock_app {
128
+ set :raise_errors, false
129
+ error(500..550) { "Error: #{response.status}" }
130
+ get '/' do
131
+ [507, {}, 'A very special error']
132
+ end
133
+ }
134
+ get '/'
135
+ assert_equal 507, status
136
+ assert_equal 'Error: 507', body
60
137
  end
61
138
 
62
- specify "raises errors when the raise_errors option is set" do
63
- Sinatra.application.options.raise_errors = true
64
- error FooError do
65
- end
66
- get '/' do
67
- raise FooError
68
- end
69
- assert_raises(FooError) { get_it('/') }
139
+ class FooError < RuntimeError
70
140
  end
71
141
 
142
+ it 'runs after exception mappings and overwrites body' do
143
+ mock_app {
144
+ set :raise_errors, false
145
+ error FooError do
146
+ response.status = 502
147
+ 'from exception mapping'
148
+ end
149
+ error(500) { 'from 500 handler' }
150
+ error(502) { 'from custom error page' }
151
+
152
+ get '/' do
153
+ raise FooError
154
+ end
155
+ }
156
+ get '/'
157
+ assert_equal 502, status
158
+ assert_equal 'from custom error page', body
159
+ end
72
160
  end
@@ -0,0 +1,58 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ describe "Middleware" do
4
+ before do
5
+ @app = mock_app(Sinatra::Default) {
6
+ get '/*' do
7
+ response.headers['X-Tests'] = env['test.ran'].join(', ')
8
+ env['PATH_INFO']
9
+ end
10
+ }
11
+ end
12
+
13
+ class MockMiddleware < Struct.new(:app)
14
+ def call(env)
15
+ (env['test.ran'] ||= []) << self.class.to_s
16
+ app.call(env)
17
+ end
18
+ end
19
+
20
+ class UpcaseMiddleware < MockMiddleware
21
+ def call(env)
22
+ env['PATH_INFO'] = env['PATH_INFO'].upcase
23
+ super
24
+ end
25
+ end
26
+
27
+ it "is added with Sinatra::Application.use" do
28
+ @app.use UpcaseMiddleware
29
+ get '/hello-world'
30
+ assert ok?
31
+ assert_equal '/HELLO-WORLD', body
32
+ end
33
+
34
+ class DowncaseMiddleware < MockMiddleware
35
+ def call(env)
36
+ env['PATH_INFO'] = env['PATH_INFO'].downcase
37
+ super
38
+ end
39
+ end
40
+
41
+ specify "runs in the order defined" do
42
+ @app.use UpcaseMiddleware
43
+ @app.use DowncaseMiddleware
44
+ get '/Foo'
45
+ assert_equal "/foo", body
46
+ assert_equal "UpcaseMiddleware, DowncaseMiddleware", response['X-Tests']
47
+ end
48
+
49
+ specify "resets the prebuilt pipeline when new middleware is added" do
50
+ @app.use UpcaseMiddleware
51
+ get '/Foo'
52
+ assert_equal "/FOO", body
53
+ @app.use DowncaseMiddleware
54
+ get '/Foo'
55
+ assert_equal '/foo', body
56
+ assert_equal "UpcaseMiddleware, DowncaseMiddleware", response['X-Tests']
57
+ end
58
+ end
@@ -0,0 +1,97 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ describe 'Options' do
4
+ before { @app = Class.new(Sinatra::Base) }
5
+
6
+ it 'sets options to literal values' do
7
+ @app.set(:foo, 'bar')
8
+ assert @app.respond_to?(:foo)
9
+ assert_equal 'bar', @app.foo
10
+ end
11
+
12
+ it 'sets options to Procs' do
13
+ @app.set(:foo, Proc.new { 'baz' })
14
+ assert @app.respond_to?(:foo)
15
+ assert_equal 'baz', @app.foo
16
+ end
17
+
18
+ it "sets multiple options with a Hash" do
19
+ @app.set :foo => 1234,
20
+ :bar => 'Hello World',
21
+ :baz => Proc.new { 'bizzle' }
22
+ assert_equal 1234, @app.foo
23
+ assert_equal 'Hello World', @app.bar
24
+ assert_equal 'bizzle', @app.baz
25
+ end
26
+
27
+ it 'inherits option methods when subclassed' do
28
+ @app.set :foo, 'bar'
29
+ @app.set :biz, Proc.new { 'baz' }
30
+
31
+ sub = Class.new(@app)
32
+ assert sub.respond_to?(:foo)
33
+ assert_equal 'bar', sub.foo
34
+ assert sub.respond_to?(:biz)
35
+ assert_equal 'baz', sub.biz
36
+ end
37
+
38
+ it 'overrides options in subclass' do
39
+ @app.set :foo, 'bar'
40
+ @app.set :biz, Proc.new { 'baz' }
41
+ sub = Class.new(@app)
42
+ sub.set :foo, 'bling'
43
+ assert_equal 'bling', sub.foo
44
+ assert_equal 'bar', @app.foo
45
+ end
46
+
47
+ it 'creates setter methods when first defined' do
48
+ @app.set :foo, 'bar'
49
+ assert @app.respond_to?('foo=')
50
+ @app.foo = 'biz'
51
+ assert_equal 'biz', @app.foo
52
+ end
53
+
54
+ it 'creates predicate methods when first defined' do
55
+ @app.set :foo, 'hello world'
56
+ assert @app.respond_to?(:foo?)
57
+ assert @app.foo?
58
+ @app.set :foo, nil
59
+ assert !@app.foo?
60
+ end
61
+
62
+ it 'uses existing setter methods if detected' do
63
+ class << @app
64
+ def foo
65
+ @foo
66
+ end
67
+ def foo=(value)
68
+ @foo = 'oops'
69
+ end
70
+ end
71
+
72
+ @app.set :foo, 'bam'
73
+ assert_equal 'oops', @app.foo
74
+ end
75
+
76
+ it "sets multiple options to true with #enable" do
77
+ @app.enable :sessions, :foo, :bar
78
+ assert @app.sessions
79
+ assert @app.foo
80
+ assert @app.bar
81
+ end
82
+
83
+ it "sets multiple options to false with #disable" do
84
+ @app.disable :sessions, :foo, :bar
85
+ assert !@app.sessions
86
+ assert !@app.foo
87
+ assert !@app.bar
88
+ end
89
+
90
+ it 'enables MethodOverride middleware when :methodoverride is enabled' do
91
+ @app.set :methodoverride, true
92
+ @app.put('/') { 'okay' }
93
+ post '/', {'_method'=>'PUT'}, {}
94
+ assert_equal 200, status
95
+ assert_equal 'okay', body
96
+ end
97
+ end
@@ -0,0 +1,61 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ $reload_count = 0
4
+ $reload_app = nil
5
+
6
+ describe "Reloading" do
7
+ before {
8
+ @app = mock_app(Sinatra::Default)
9
+ $reload_app = @app
10
+ }
11
+
12
+ after {
13
+ $reload_app = nil
14
+ }
15
+
16
+ it 'is enabled by default when in development and the app_file is set' do
17
+ @app.set :app_file, __FILE__
18
+ @app.set :environment, :development
19
+ assert_same true, @app.reload
20
+ assert_same true, @app.reload?
21
+ end
22
+
23
+ it 'is disabled by default when running in non-development environment' do
24
+ @app.set :app_file, __FILE__
25
+ @app.set :environment, :test
26
+ assert !@app.reload
27
+ assert_same false, @app.reload?
28
+ end
29
+
30
+ it 'is disabled by default when no app_file is available' do
31
+ @app.set :app_file, nil
32
+ @app.set :environment, :development
33
+ assert !@app.reload
34
+ assert_same false, @app.reload?
35
+ end
36
+
37
+ it 'can be turned off explicitly' do
38
+ @app.set :app_file, __FILE__
39
+ @app.set :environment, :development
40
+ assert_same true, @app.reload
41
+ @app.set :reload, false
42
+ assert_same false, @app.reload
43
+ assert_same false, @app.reload?
44
+ end
45
+
46
+ it 'reloads the app_file each time a request is made' do
47
+ @app.set :app_file, File.dirname(__FILE__) + '/data/reload_app_file.rb'
48
+ @app.set :reload, true
49
+ @app.get('/') { 'Hello World' }
50
+
51
+ get '/'
52
+ assert_equal 200, status
53
+ assert_equal 'Hello from reload file', body
54
+ assert_equal 1, $reload_count
55
+
56
+ get '/'
57
+ assert_equal 200, status
58
+ assert_equal 'Hello from reload file', body
59
+ assert_equal 2, $reload_count
60
+ end
61
+ end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ describe 'Sinatra::Request' do
4
+ it 'responds to #user_agent' do
5
+ request = Sinatra::Request.new({'HTTP_USER_AGENT' => 'Test'})
6
+ assert request.respond_to?(:user_agent)
7
+ assert_equal 'Test', request.user_agent
8
+ end
9
+
10
+ it 'parses POST params when Content-Type is form-dataish' do
11
+ request = Sinatra::Request.new(
12
+ 'REQUEST_METHOD' => 'PUT',
13
+ 'CONTENT_TYPE' => 'application/x-www-form-urlencoded',
14
+ 'rack.input' => StringIO.new('foo=bar')
15
+ )
16
+ assert_equal 'bar', request.params['foo']
17
+ end
18
+ end
@@ -0,0 +1,88 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ describe 'Result Handling' do
4
+ it "sets response.body when result is a String" do
5
+ mock_app {
6
+ get '/' do
7
+ 'Hello World'
8
+ end
9
+ }
10
+
11
+ get '/'
12
+ assert ok?
13
+ assert_equal 'Hello World', body
14
+ end
15
+
16
+ it "sets response.body when result is an Array of Strings" do
17
+ mock_app {
18
+ get '/' do
19
+ ['Hello', 'World']
20
+ end
21
+ }
22
+
23
+ get '/'
24
+ assert ok?
25
+ assert_equal 'HelloWorld', body
26
+ end
27
+
28
+ it "sets response.body when result responds to #each" do
29
+ mock_app {
30
+ get '/' do
31
+ res = lambda { 'Hello World' }
32
+ def res.each ; yield call ; end
33
+ res
34
+ end
35
+ }
36
+
37
+ get '/'
38
+ assert ok?
39
+ assert_equal 'Hello World', body
40
+ end
41
+
42
+ it "sets response.body to [] when result is nil" do
43
+ mock_app {
44
+ get '/' do
45
+ nil
46
+ end
47
+ }
48
+
49
+ get '/'
50
+ assert ok?
51
+ assert_equal '', body
52
+ end
53
+
54
+ it "sets status, headers, and body when result is a Rack response tuple" do
55
+ mock_app {
56
+ get '/' do
57
+ [205, {'Content-Type' => 'foo/bar'}, 'Hello World']
58
+ end
59
+ }
60
+
61
+ get '/'
62
+ assert_equal 205, status
63
+ assert_equal 'foo/bar', response['Content-Type']
64
+ assert_equal 'Hello World', body
65
+ end
66
+
67
+ it "sets status and body when result is a two-tuple" do
68
+ mock_app {
69
+ get '/' do
70
+ [409, 'formula of']
71
+ end
72
+ }
73
+
74
+ get '/'
75
+ assert_equal 409, status
76
+ assert_equal 'formula of', body
77
+ end
78
+
79
+ it "sets status when result is a Fixnum status code" do
80
+ mock_app {
81
+ get('/') { 205 }
82
+ }
83
+
84
+ get '/'
85
+ assert_equal 205, status
86
+ assert_equal '', body
87
+ end
88
+ end