rtomayko-sinatra 0.3.3 → 0.8.9

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