sinatra-base 1.0

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 (58) hide show
  1. data/AUTHORS +43 -0
  2. data/CHANGES +511 -0
  3. data/LICENSE +22 -0
  4. data/README.jp.rdoc +552 -0
  5. data/README.rdoc +636 -0
  6. data/Rakefile +116 -0
  7. data/lib/sinatra.rb +7 -0
  8. data/lib/sinatra/base.rb +1167 -0
  9. data/lib/sinatra/images/404.png +0 -0
  10. data/lib/sinatra/images/500.png +0 -0
  11. data/lib/sinatra/main.rb +28 -0
  12. data/lib/sinatra/showexceptions.rb +307 -0
  13. data/lib/sinatra/tilt.rb +746 -0
  14. data/sinatra-base.gemspec +94 -0
  15. data/test/base_test.rb +160 -0
  16. data/test/builder_test.rb +65 -0
  17. data/test/contest.rb +64 -0
  18. data/test/erb_test.rb +81 -0
  19. data/test/erubis_test.rb +82 -0
  20. data/test/extensions_test.rb +100 -0
  21. data/test/filter_test.rb +221 -0
  22. data/test/haml_test.rb +95 -0
  23. data/test/helper.rb +76 -0
  24. data/test/helpers_test.rb +582 -0
  25. data/test/less_test.rb +37 -0
  26. data/test/mapped_error_test.rb +197 -0
  27. data/test/middleware_test.rb +68 -0
  28. data/test/public/favicon.ico +0 -0
  29. data/test/request_test.rb +33 -0
  30. data/test/response_test.rb +42 -0
  31. data/test/result_test.rb +98 -0
  32. data/test/route_added_hook_test.rb +59 -0
  33. data/test/routing_test.rb +860 -0
  34. data/test/sass_test.rb +85 -0
  35. data/test/server_test.rb +47 -0
  36. data/test/settings_test.rb +368 -0
  37. data/test/sinatra_test.rb +13 -0
  38. data/test/static_test.rb +93 -0
  39. data/test/templates_test.rb +159 -0
  40. data/test/views/error.builder +3 -0
  41. data/test/views/error.erb +3 -0
  42. data/test/views/error.erubis +3 -0
  43. data/test/views/error.haml +3 -0
  44. data/test/views/error.sass +2 -0
  45. data/test/views/foo/hello.test +1 -0
  46. data/test/views/hello.builder +1 -0
  47. data/test/views/hello.erb +1 -0
  48. data/test/views/hello.erubis +1 -0
  49. data/test/views/hello.haml +1 -0
  50. data/test/views/hello.less +5 -0
  51. data/test/views/hello.sass +2 -0
  52. data/test/views/hello.test +1 -0
  53. data/test/views/layout2.builder +3 -0
  54. data/test/views/layout2.erb +2 -0
  55. data/test/views/layout2.erubis +2 -0
  56. data/test/views/layout2.haml +2 -0
  57. data/test/views/layout2.test +1 -0
  58. metadata +257 -0
@@ -0,0 +1,82 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+ require 'erubis'
3
+
4
+ class ERubisTest < Test::Unit::TestCase
5
+ def erubis_app(&block)
6
+ mock_app {
7
+ set :views, File.dirname(__FILE__) + '/views'
8
+ get '/', &block
9
+ }
10
+ get '/'
11
+ end
12
+
13
+ it 'renders inline ERubis strings' do
14
+ erubis_app { erubis '<%= 1 + 1 %>' }
15
+ assert ok?
16
+ assert_equal '2', body
17
+ end
18
+
19
+ it 'renders .erubis files in views path' do
20
+ erubis_app { erubis :hello }
21
+ assert ok?
22
+ assert_equal "Hello World\n", body
23
+ end
24
+
25
+ it 'takes a :locals option' do
26
+ erubis_app {
27
+ locals = {:foo => 'Bar'}
28
+ erubis '<%= foo %>', :locals => locals
29
+ }
30
+ assert ok?
31
+ assert_equal 'Bar', body
32
+ end
33
+
34
+ it "renders with inline layouts" do
35
+ mock_app {
36
+ layout { 'THIS. IS. <%= yield.upcase %>!' }
37
+ get('/') { erubis 'Sparta' }
38
+ }
39
+ get '/'
40
+ assert ok?
41
+ assert_equal 'THIS. IS. SPARTA!', body
42
+ end
43
+
44
+ it "renders with file layouts" do
45
+ erubis_app {
46
+ erubis 'Hello World', :layout => :layout2
47
+ }
48
+ assert ok?
49
+ assert_equal "ERubis Layout!\nHello World\n", body
50
+ end
51
+
52
+ it "renders erubis with blocks" do
53
+ mock_app {
54
+ def container
55
+ @_out_buf << "THIS."
56
+ yield
57
+ @_out_buf << "SPARTA!"
58
+ end
59
+ def is; "IS." end
60
+ get '/' do
61
+ erubis '<% container do %> <%= is %> <% end %>'
62
+ end
63
+ }
64
+ get '/'
65
+ assert ok?
66
+ assert_equal 'THIS. IS. SPARTA!', body
67
+ end
68
+
69
+ it "can be used in a nested fashion for partials and whatnot" do
70
+ mock_app {
71
+ template(:inner) { "<inner><%= 'hi' %></inner>" }
72
+ template(:outer) { "<outer><%= erubis :inner %></outer>" }
73
+ get '/' do
74
+ erubis :outer
75
+ end
76
+ }
77
+
78
+ get '/'
79
+ assert ok?
80
+ assert_equal '<outer><inner>hi</inner></outer>', body
81
+ end
82
+ end
@@ -0,0 +1,100 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class ExtensionsTest < Test::Unit::TestCase
4
+ module FooExtensions
5
+ def foo
6
+ end
7
+
8
+ private
9
+ def im_hiding_in_ur_foos
10
+ end
11
+ end
12
+
13
+ module BarExtensions
14
+ def bar
15
+ end
16
+ end
17
+
18
+ module BazExtensions
19
+ def baz
20
+ end
21
+ end
22
+
23
+ module QuuxExtensions
24
+ def quux
25
+ end
26
+ end
27
+
28
+ module PainExtensions
29
+ def foo=(name); end
30
+ def bar?(name); end
31
+ def fizz!(name); end
32
+ end
33
+
34
+ it 'will add the methods to the DSL for the class in which you register them and its subclasses' do
35
+ Sinatra::Base.register FooExtensions
36
+ assert Sinatra::Base.respond_to?(:foo)
37
+
38
+ Sinatra::Application.register BarExtensions
39
+ assert Sinatra::Application.respond_to?(:bar)
40
+ assert Sinatra::Application.respond_to?(:foo)
41
+ assert !Sinatra::Base.respond_to?(:bar)
42
+ end
43
+
44
+ it 'allows extending by passing a block' do
45
+ Sinatra::Base.register {
46
+ def im_in_ur_anonymous_module; end
47
+ }
48
+ assert Sinatra::Base.respond_to?(:im_in_ur_anonymous_module)
49
+ end
50
+
51
+ it 'will make sure any public methods added via Application#register are delegated to Sinatra::Delegator' do
52
+ Sinatra::Application.register FooExtensions
53
+ assert Sinatra::Delegator.private_instance_methods.
54
+ map { |m| m.to_sym }.include?(:foo)
55
+ assert !Sinatra::Delegator.private_instance_methods.
56
+ map { |m| m.to_sym }.include?(:im_hiding_in_ur_foos)
57
+ end
58
+
59
+ it 'will handle special method names' do
60
+ Sinatra::Application.register PainExtensions
61
+ assert Sinatra::Delegator.private_instance_methods.
62
+ map { |m| m.to_sym }.include?(:foo=)
63
+ assert Sinatra::Delegator.private_instance_methods.
64
+ map { |m| m.to_sym }.include?(:bar?)
65
+ assert Sinatra::Delegator.private_instance_methods.
66
+ map { |m| m.to_sym }.include?(:fizz!)
67
+ end
68
+
69
+ it 'will not delegate methods on Base#register' do
70
+ Sinatra::Base.register QuuxExtensions
71
+ assert !Sinatra::Delegator.private_instance_methods.include?("quux")
72
+ end
73
+
74
+ it 'will extend the Sinatra::Application application by default' do
75
+ Sinatra.register BazExtensions
76
+ assert !Sinatra::Base.respond_to?(:baz)
77
+ assert Sinatra::Application.respond_to?(:baz)
78
+ end
79
+
80
+ module BizzleExtension
81
+ def bizzle
82
+ bizzle_option
83
+ end
84
+
85
+ def self.registered(base)
86
+ fail "base should be BizzleApp" unless base == BizzleApp
87
+ fail "base should have already extended BizzleExtension" unless base.respond_to?(:bizzle)
88
+ base.set :bizzle_option, 'bizzle!'
89
+ end
90
+ end
91
+
92
+ class BizzleApp < Sinatra::Base
93
+ end
94
+
95
+ it 'sends .registered to the extension module after extending the class' do
96
+ BizzleApp.register BizzleExtension
97
+ assert_equal 'bizzle!', BizzleApp.bizzle_option
98
+ assert_equal 'bizzle!', BizzleApp.bizzle
99
+ end
100
+ end
@@ -0,0 +1,221 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class BeforeFilterTest < Test::Unit::TestCase
4
+ it "executes filters in the order defined" do
5
+ count = 0
6
+ mock_app do
7
+ get('/') { 'Hello World' }
8
+ before {
9
+ assert_equal 0, count
10
+ count = 1
11
+ }
12
+ before {
13
+ assert_equal 1, count
14
+ count = 2
15
+ }
16
+ end
17
+
18
+ get '/'
19
+ assert ok?
20
+ assert_equal 2, count
21
+ assert_equal 'Hello World', body
22
+ end
23
+
24
+ it "can modify the request" do
25
+ mock_app {
26
+ get('/foo') { 'foo' }
27
+ get('/bar') { 'bar' }
28
+ before { request.path_info = '/bar' }
29
+ }
30
+
31
+ get '/foo'
32
+ assert ok?
33
+ assert_equal 'bar', body
34
+ end
35
+
36
+ it "can modify instance variables available to routes" do
37
+ mock_app {
38
+ before { @foo = 'bar' }
39
+ get('/foo') { @foo }
40
+ }
41
+
42
+ get '/foo'
43
+ assert ok?
44
+ assert_equal 'bar', body
45
+ end
46
+
47
+ it "allows redirects" do
48
+ mock_app {
49
+ before { redirect '/bar' }
50
+ get('/foo') do
51
+ fail 'before block should have halted processing'
52
+ 'ORLY?!'
53
+ end
54
+ }
55
+
56
+ get '/foo'
57
+ assert redirect?
58
+ assert_equal '/bar', response['Location']
59
+ assert_equal '', body
60
+ end
61
+
62
+ it "does not modify the response with its return value" do
63
+ mock_app {
64
+ before { 'Hello World!' }
65
+ get '/foo' do
66
+ assert_equal [], response.body
67
+ 'cool'
68
+ end
69
+ }
70
+
71
+ get '/foo'
72
+ assert ok?
73
+ assert_equal 'cool', body
74
+ end
75
+
76
+ it "does modify the response with halt" do
77
+ mock_app {
78
+ before { halt 302, 'Hi' }
79
+ get '/foo' do
80
+ "should not happen"
81
+ end
82
+ }
83
+
84
+ get '/foo'
85
+ assert_equal 302, response.status
86
+ assert_equal 'Hi', body
87
+ end
88
+
89
+ it "gives you access to params" do
90
+ mock_app {
91
+ before { @foo = params['foo'] }
92
+ get('/foo') { @foo }
93
+ }
94
+
95
+ get '/foo?foo=cool'
96
+ assert ok?
97
+ assert_equal 'cool', body
98
+ end
99
+
100
+ it "runs filters defined in superclasses" do
101
+ base = Class.new(Sinatra::Base)
102
+ base.before { @foo = 'hello from superclass' }
103
+
104
+ mock_app(base) {
105
+ get('/foo') { @foo }
106
+ }
107
+
108
+ get '/foo'
109
+ assert_equal 'hello from superclass', body
110
+ end
111
+
112
+ it 'does not run before filter when serving static files' do
113
+ ran_filter = false
114
+ mock_app {
115
+ before { ran_filter = true }
116
+ set :static, true
117
+ set :public, File.dirname(__FILE__)
118
+ }
119
+ get "/#{File.basename(__FILE__)}"
120
+ assert ok?
121
+ assert_equal File.read(__FILE__), body
122
+ assert !ran_filter
123
+ end
124
+ end
125
+
126
+ class AfterFilterTest < Test::Unit::TestCase
127
+ it "executes filters in the order defined" do
128
+ invoked = 0
129
+ mock_app do
130
+ before { invoked = 2 }
131
+ get('/') { invoked += 2 }
132
+ after { invoked *= 2 }
133
+ end
134
+
135
+ get '/'
136
+ assert ok?
137
+
138
+ assert_equal 8, invoked
139
+ end
140
+
141
+ it "executes filters in the order defined" do
142
+ count = 0
143
+ mock_app do
144
+ get('/') { 'Hello World' }
145
+ after {
146
+ assert_equal 0, count
147
+ count = 1
148
+ }
149
+ after {
150
+ assert_equal 1, count
151
+ count = 2
152
+ }
153
+ end
154
+
155
+ get '/'
156
+ assert ok?
157
+ assert_equal 2, count
158
+ assert_equal 'Hello World', body
159
+ end
160
+
161
+ it "allows redirects" do
162
+ mock_app {
163
+ get('/foo') { 'ORLY' }
164
+ after { redirect '/bar' }
165
+ }
166
+
167
+ get '/foo'
168
+ assert redirect?
169
+ assert_equal '/bar', response['Location']
170
+ assert_equal '', body
171
+ end
172
+
173
+ it "does not modify the response with its return value" do
174
+ mock_app {
175
+ get('/foo') { 'cool' }
176
+ after { 'Hello World!' }
177
+ }
178
+
179
+ get '/foo'
180
+ assert ok?
181
+ assert_equal 'cool', body
182
+ end
183
+
184
+ it "does modify the response with halt" do
185
+ mock_app {
186
+ get '/foo' do
187
+ "should not be returned"
188
+ end
189
+ after { halt 302, 'Hi' }
190
+ }
191
+
192
+ get '/foo'
193
+ assert_equal 302, response.status
194
+ assert_equal 'Hi', body
195
+ end
196
+
197
+ it "runs filters defined in superclasses" do
198
+ count = 2
199
+ base = Class.new(Sinatra::Base)
200
+ base.after { count *= 2 }
201
+ mock_app(base) {
202
+ get('/foo') { count += 2 }
203
+ }
204
+
205
+ get '/foo'
206
+ assert_equal 8, count
207
+ end
208
+
209
+ it 'does not run after filter when serving static files' do
210
+ ran_filter = false
211
+ mock_app {
212
+ after { ran_filter = true }
213
+ set :static, true
214
+ set :public, File.dirname(__FILE__)
215
+ }
216
+ get "/#{File.basename(__FILE__)}"
217
+ assert ok?
218
+ assert_equal File.read(__FILE__), body
219
+ assert !ran_filter
220
+ end
221
+ end
@@ -0,0 +1,95 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ begin
4
+ require 'haml'
5
+
6
+ class HAMLTest < Test::Unit::TestCase
7
+ def haml_app(&block)
8
+ mock_app {
9
+ set :views, File.dirname(__FILE__) + '/views'
10
+ get '/', &block
11
+ }
12
+ get '/'
13
+ end
14
+
15
+ it 'renders inline HAML strings' do
16
+ haml_app { haml '%h1 Hiya' }
17
+ assert ok?
18
+ assert_equal "<h1>Hiya</h1>\n", body
19
+ end
20
+
21
+ it 'renders .haml files in views path' do
22
+ haml_app { haml :hello }
23
+ assert ok?
24
+ assert_equal "<h1>Hello From Haml</h1>\n", body
25
+ end
26
+
27
+ it "renders with inline layouts" do
28
+ mock_app {
29
+ layout { %q(%h1= 'THIS. IS. ' + yield.upcase) }
30
+ get('/') { haml '%em Sparta' }
31
+ }
32
+ get '/'
33
+ assert ok?
34
+ assert_equal "<h1>THIS. IS. <EM>SPARTA</EM></h1>\n", body
35
+ end
36
+
37
+ it "renders with file layouts" do
38
+ haml_app {
39
+ haml 'Hello World', :layout => :layout2
40
+ }
41
+ assert ok?
42
+ assert_equal "<h1>HAML Layout!</h1>\n<p>Hello World</p>\n", body
43
+ end
44
+
45
+ it "raises error if template not found" do
46
+ mock_app {
47
+ get('/') { haml :no_such_template }
48
+ }
49
+ assert_raise(Errno::ENOENT) { get('/') }
50
+ end
51
+
52
+ it "passes HAML options to the Haml engine" do
53
+ mock_app {
54
+ get '/' do
55
+ haml "!!!\n%h1 Hello World", :format => :html5
56
+ end
57
+ }
58
+ get '/'
59
+ assert ok?
60
+ assert_equal "<!DOCTYPE html>\n<h1>Hello World</h1>\n", body
61
+ end
62
+
63
+ it "passes default HAML options to the Haml engine" do
64
+ mock_app {
65
+ set :haml, {:format => :html5}
66
+ get '/' do
67
+ haml "!!!\n%h1 Hello World"
68
+ end
69
+ }
70
+ get '/'
71
+ assert ok?
72
+ assert_equal "<!DOCTYPE html>\n<h1>Hello World</h1>\n", body
73
+ end
74
+
75
+ it "merges the default HAML options with the overrides and passes them to the Haml engine" do
76
+ mock_app {
77
+ set :haml, {:format => :html5, :attr_wrapper => '"'} # default HAML attr are <tag attr='single-quoted'>
78
+ get '/' do
79
+ haml "!!!\n%h1{:class => :header} Hello World"
80
+ end
81
+ get '/html4' do
82
+ haml "!!!\n%h1{:class => 'header'} Hello World", :format => :html4
83
+ end
84
+ }
85
+ get '/'
86
+ assert ok?
87
+ assert_equal "<!DOCTYPE html>\n<h1 class=\"header\">Hello World</h1>\n", body
88
+ get '/html4'
89
+ assert ok?
90
+ assert_match(/^<!DOCTYPE html PUBLIC (.*) HTML 4.01/, body)
91
+ end
92
+ end
93
+ rescue
94
+ warn "#{$!.to_s}: skipping haml tests"
95
+ end