adamwiggins-sinatra 0.8.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/AUTHORS +40 -0
  2. data/CHANGES +167 -0
  3. data/LICENSE +22 -0
  4. data/README.rdoc +529 -0
  5. data/Rakefile +180 -0
  6. data/compat/app_test.rb +300 -0
  7. data/compat/application_test.rb +334 -0
  8. data/compat/builder_test.rb +101 -0
  9. data/compat/custom_error_test.rb +62 -0
  10. data/compat/erb_test.rb +136 -0
  11. data/compat/events_test.rb +75 -0
  12. data/compat/filter_test.rb +30 -0
  13. data/compat/haml_test.rb +233 -0
  14. data/compat/helper.rb +21 -0
  15. data/compat/mapped_error_test.rb +72 -0
  16. data/compat/pipeline_test.rb +71 -0
  17. data/compat/public/foo.xml +1 -0
  18. data/compat/sass_test.rb +57 -0
  19. data/compat/sessions_test.rb +39 -0
  20. data/compat/streaming_test.rb +121 -0
  21. data/compat/sym_params_test.rb +19 -0
  22. data/compat/template_test.rb +30 -0
  23. data/compat/use_in_file_templates_test.rb +47 -0
  24. data/compat/views/foo.builder +1 -0
  25. data/compat/views/foo.erb +1 -0
  26. data/compat/views/foo.haml +1 -0
  27. data/compat/views/foo.sass +2 -0
  28. data/compat/views/foo_layout.erb +2 -0
  29. data/compat/views/foo_layout.haml +2 -0
  30. data/compat/views/layout_test/foo.builder +1 -0
  31. data/compat/views/layout_test/foo.erb +1 -0
  32. data/compat/views/layout_test/foo.haml +1 -0
  33. data/compat/views/layout_test/foo.sass +2 -0
  34. data/compat/views/layout_test/layout.builder +3 -0
  35. data/compat/views/layout_test/layout.erb +1 -0
  36. data/compat/views/layout_test/layout.haml +1 -0
  37. data/compat/views/layout_test/layout.sass +2 -0
  38. data/compat/views/no_layout/no_layout.builder +1 -0
  39. data/compat/views/no_layout/no_layout.haml +1 -0
  40. data/lib/sinatra/base.rb +818 -0
  41. data/lib/sinatra/compat.rb +239 -0
  42. data/lib/sinatra/images/404.png +0 -0
  43. data/lib/sinatra/images/500.png +0 -0
  44. data/lib/sinatra/main.rb +48 -0
  45. data/lib/sinatra/test/rspec.rb +2 -0
  46. data/lib/sinatra/test/spec.rb +2 -0
  47. data/lib/sinatra/test/unit.rb +11 -0
  48. data/lib/sinatra/test.rb +112 -0
  49. data/lib/sinatra.rb +3 -0
  50. data/sinatra.gemspec +107 -0
  51. data/test/base_test.rb +72 -0
  52. data/test/builder_test.rb +68 -0
  53. data/test/data/reload_app_file.rb +3 -0
  54. data/test/erb_test.rb +55 -0
  55. data/test/filter_test.rb +39 -0
  56. data/test/haml_test.rb +72 -0
  57. data/test/helpers_test.rb +368 -0
  58. data/test/mapped_error_test.rb +164 -0
  59. data/test/middleware_test.rb +63 -0
  60. data/test/options_test.rb +103 -0
  61. data/test/reload_test.rb +65 -0
  62. data/test/request_test.rb +11 -0
  63. data/test/result_test.rb +92 -0
  64. data/test/routing_test.rb +338 -0
  65. data/test/sass_test.rb +40 -0
  66. data/test/sinatra_test.rb +15 -0
  67. data/test/static_test.rb +60 -0
  68. data/test/templates_test.rb +92 -0
  69. data/test/views/hello.builder +1 -0
  70. data/test/views/hello.erb +1 -0
  71. data/test/views/hello.haml +1 -0
  72. data/test/views/hello.sass +2 -0
  73. data/test/views/hello.test +1 -0
  74. data/test/views/layout2.builder +3 -0
  75. data/test/views/layout2.erb +2 -0
  76. data/test/views/layout2.haml +2 -0
  77. data/test/views/layout2.test +1 -0
  78. metadata +159 -0
@@ -0,0 +1,239 @@
1
+ # Sinatra 0.3.x compatibility module.
2
+ #
3
+ # The following code makes Sinatra 0.9.x compatible with Sinatra 0.3.x to
4
+ # ease the transition to the final 1.0 release. Everything defined in this
5
+ # file will be removed for the 1.0 release.
6
+
7
+ require 'ostruct'
8
+ require 'sinatra/base'
9
+ require 'sinatra/main'
10
+
11
+ # Like Kernel#warn but outputs the location that triggered the warning.
12
+ def sinatra_warn(*message)
13
+ line = caller.
14
+ detect { |line| line !~ /(?:lib\/sinatra\/|__DELEGATE__)/ }.
15
+ sub(/:in .*/, '')
16
+ warn "#{line}: warning: #{message.join(' ')}"
17
+ end
18
+
19
+ # Rack now supports evented and swiftiplied mongrels through separate
20
+ # handler.
21
+ if ENV['SWIFT']
22
+ sinatra_warn 'the SWIFT environment variable is deprecated;',
23
+ 'use Rack::Handler::SwiftipliedMongrel instead.'
24
+ require 'swiftcore/swiftiplied_mongrel'
25
+ puts "Using Swiftiplied Mongrel"
26
+ elsif ENV['EVENT']
27
+ sinatra_warn 'the EVENT environment variable is deprecated;',
28
+ 'use Rack::Handler::EventedMongrel instead.'
29
+ require 'swiftcore/evented_mongrel'
30
+ puts "Using Evented Mongrel"
31
+ end
32
+
33
+ # Make Rack 0.9.0 backward compatibile with 0.4.0 mime types. This isn't
34
+ # technically a Sinatra issue but many Sinatra apps access the old
35
+ # MIME_TYPES constants due to Sinatra example code.
36
+ require 'rack/file'
37
+ class Rack::File
38
+ def self.const_missing(const_name)
39
+ if const_name == :MIME_TYPES
40
+ hash = Hash.new { |hash,key| Rack::Mime::MIME_TYPES[".#{key}"] }
41
+ const_set :MIME_TYPES, hash
42
+ sinatra_warn 'Rack::File::MIME_TYPES is deprecated; use Rack::Mime instead.'
43
+ hash
44
+ else
45
+ super
46
+ end
47
+ end
48
+ end
49
+
50
+ module Sinatra
51
+ module Compat
52
+ end
53
+
54
+ # The ServerError exception is deprecated. Any exception is considered an
55
+ # internal server error.
56
+ class ServerError < RuntimeError
57
+ def initialize(*args, &block)
58
+ sinatra_warn 'Sinatra::ServerError is deprecated;',
59
+ 'use another exception, error, or Kernel#fail instead.'
60
+ end
61
+ def code ; 500 ; end
62
+ end
63
+
64
+ class Default < Base
65
+ def self.const_missing(const_name)
66
+ if const_name == :FORWARD_METHODS
67
+ sinatra_warn 'Sinatra::Application::FORWARD_METHODS is deprecated;',
68
+ 'use Sinatra::Delegator::METHODS instead.'
69
+ const_set :FORWARD_METHODS, Sinatra::Delegator::METHODS
70
+ Sinatra::Delegator::METHODS
71
+ else
72
+ super
73
+ end
74
+ end
75
+
76
+ # Deprecated. Use: response['Header-Name']
77
+ def headers(header=nil)
78
+ sinatra_warn "The 'headers' method is deprecated; use 'response' instead."
79
+ response.headers.merge!(header) if header
80
+ response.headers
81
+ end
82
+ alias :header :headers
83
+
84
+ # Deprecated. Use: halt
85
+ def stop(*args, &block)
86
+ sinatra_warn "The 'stop' method is deprecated; use 'halt' instead."
87
+ halt(*args, &block)
88
+ end
89
+
90
+ # Deprecated. Use: etag
91
+ def entity_tag(*args, &block)
92
+ sinatra_warn "The 'entity_tag' method is deprecated; use 'etag' instead."
93
+ etag(*args, &block)
94
+ end
95
+
96
+ # The :disposition option is deprecated; use: #attachment. This method
97
+ # setting the Content-Transfer-Encoding header is deprecated.
98
+ #--
99
+ # TODO deprecation warning for :disposition argument.
100
+ def send_file(path, opts={})
101
+ opts[:disposition] = 'attachment' if !opts.key?(:disposition)
102
+ attachment opts[:filename] || path if opts[:filename] || opts[:disposition]
103
+ response['Content-Transfer-Encoding'] = 'binary' if opts[:disposition]
104
+ super(path, opts)
105
+ end
106
+
107
+ # Throwing halt with a Symbol and the to_result convention are
108
+ # deprecated. Override the invoke method to detect those types of return
109
+ # values.
110
+ def invoke(handler)
111
+ res = super
112
+ case
113
+ when res.kind_of?(Symbol)
114
+ sinatra_warn "Invoking the :#{res} helper by returning a Symbol is deprecated;",
115
+ "call the helper directly instead."
116
+ @response.body = __send__(res)
117
+ when res.respond_to?(:to_result)
118
+ sinatra_warn "The to_result convention is deprecated."
119
+ @response.body = res.to_result(self)
120
+ end
121
+ res
122
+ end
123
+
124
+ def options
125
+ Options.new(self.class)
126
+ end
127
+
128
+ class Options < Struct.new(:target) #:nodoc:
129
+ def method_missing(name, *args, &block)
130
+ if target.respond_to?(name)
131
+ target.__send__(name, *args, &block)
132
+ elsif args.empty? && name.to_s !~ /=$/
133
+ sinatra_warn 'accessing undefined options will raise a NameError in Sinatra 1.0'
134
+ nil
135
+ else
136
+ super
137
+ end
138
+ end
139
+ end
140
+
141
+ class << self
142
+ # Deprecated. Options are stored directly on the class object.
143
+ def options
144
+ sinatra_warn "The 'options' class method is deprecated; use 'self' instead."
145
+ Options.new(self)
146
+ end
147
+
148
+ # Deprecated. Use: configure
149
+ def configures(*args, &block)
150
+ sinatra_warn "The 'configures' method is deprecated; use 'configure' instead."
151
+ configure(*args, &block)
152
+ end
153
+
154
+ # Deprecated. Use: set
155
+ def default_options
156
+ sinatra_warn "Sinatra::Application.default_options is deprecated; use 'set' instead."
157
+ fake = lambda { |options| set(options) }
158
+ def fake.merge!(options) ; call(options) ; end
159
+ fake
160
+ end
161
+
162
+ # Deprecated. Use: set
163
+ def set_option(*args, &block)
164
+ sinatra_warn "The 'set_option' method is deprecated; use 'set' instead."
165
+ set(*args, &block)
166
+ end
167
+
168
+ def set_options(*args, &block)
169
+ sinatra_warn "The 'set_options' method is deprecated; use 'set' instead."
170
+ set(*args, &block)
171
+ end
172
+
173
+ # Deprecated. Use: set :environment, ENV
174
+ def env=(value)
175
+ sinatra_warn "The :env option is deprecated; use :environment instead."
176
+ set :environment, value
177
+ end
178
+
179
+ # Deprecated. Use: options.environment
180
+ def env
181
+ sinatra_warn "The :env option is deprecated; use :environment instead."
182
+ environment
183
+ end
184
+ end
185
+
186
+ # Deprecated. Missing messages are no longer delegated to @response.
187
+ def method_missing(name, *args, &b)
188
+ if @response.respond_to?(name)
189
+ sinatra_warn "The '#{name}' method is deprecated; use 'response.#{name}' instead."
190
+ @response.send(name, *args, &b)
191
+ else
192
+ super
193
+ end
194
+ end
195
+ end
196
+
197
+ class << self
198
+ # Deprecated. Use: Sinatra::Application
199
+ def application
200
+ sinatra_warn "Sinatra.application is deprecated; use Sinatra::Application instead."
201
+ Sinatra::Application
202
+ end
203
+
204
+ # Deprecated. Use: Sinatra::Application.reset!
205
+ def application=(value)
206
+ raise ArgumentError unless value.nil?
207
+ sinatra_warn "Setting Sinatra.application to nil is deprecated; create a new instance instead."
208
+ Sinatra.class_eval do
209
+ remove_const :Application
210
+ const_set :Application, Class.new(Sinatra::Default)
211
+ end
212
+ end
213
+
214
+ def build_application
215
+ sinatra_warn "Sinatra.build_application is deprecated; use Sinatra::Application instead."
216
+ Sinatra::Application
217
+ end
218
+
219
+ def options
220
+ sinatra_warn "Sinatra.options is deprecated; use Sinatra::Application.option_name instead."
221
+ Sinatra::Application.options
222
+ end
223
+
224
+ def port
225
+ sinatra_warn "Sinatra.port is deprecated; use Sinatra::Application.port instead."
226
+ options.port
227
+ end
228
+
229
+ def host
230
+ sinatra_warn "Sinatra.host is deprecated; use Sinatra::Application.host instead."
231
+ options.host
232
+ end
233
+
234
+ def env
235
+ sinatra_warn "Sinatra.env is deprecated; use Sinatra::Application.environment instead."
236
+ options.environment
237
+ end
238
+ end
239
+ end
Binary file
Binary file
@@ -0,0 +1,48 @@
1
+ require 'sinatra/base'
2
+
3
+ module Sinatra
4
+ class Default < Base
5
+ set :app_file, lambda {
6
+ ignore = [
7
+ /lib\/sinatra.*\.rb$/, # all sinatra code
8
+ /\(.*\)/, # generated code
9
+ /custom_require\.rb$/ # rubygems require hacks
10
+ ]
11
+ path =
12
+ caller.map{ |line| line.split(':', 2).first }.find do |file|
13
+ next if ignore.any? { |pattern| file =~ pattern }
14
+ file
15
+ end
16
+ path || $0
17
+ }.call
18
+
19
+ set :run, Proc.new { $0 == app_file }
20
+ set :reload, Proc.new{ app_file? && development? }
21
+
22
+ if run? && ARGV.any?
23
+ require 'optparse'
24
+ OptionParser.new { |op|
25
+ op.on('-x') { set :mutex, true }
26
+ op.on('-e env') { |val| set :environment, val.to_sym }
27
+ op.on('-s server') { |val| set :server, val }
28
+ op.on('-p port') { |val| set :port, val.to_i }
29
+ }.parse!(ARGV.dup)
30
+ end
31
+ end
32
+ end
33
+
34
+ include Sinatra::Delegator
35
+
36
+ def helpers(&block)
37
+ Sinatra::Application.send :class_eval, &block
38
+ end
39
+
40
+ def mime(ext, type)
41
+ ext = ".#{ext}" unless ext.to_s[0] == ?.
42
+ Rack::Mime::MIME_TYPES[ext.to_s] = type
43
+ end
44
+
45
+ at_exit do
46
+ raise $! if $!
47
+ Sinatra::Application.run! if Sinatra::Application.run?
48
+ end
@@ -0,0 +1,2 @@
1
+ require 'sinatra/test'
2
+ require 'spec/interop/test'
@@ -0,0 +1,2 @@
1
+ require 'test/spec'
2
+ require 'sinatra/test'
@@ -0,0 +1,11 @@
1
+ require 'test/unit'
2
+ require 'sinatra/test'
3
+
4
+ Test::Unit::TestCase.send :include, Sinatra::Test
5
+
6
+ Sinatra::Default.set(
7
+ :env => :test,
8
+ :run => false,
9
+ :raise_errors => true,
10
+ :logging => false
11
+ )
@@ -0,0 +1,112 @@
1
+ require 'sinatra/base'
2
+ require 'test/unit'
3
+
4
+ module Sinatra::Test
5
+ include Rack::Utils
6
+
7
+ attr_reader :app, :request, :response
8
+
9
+ def mock_app(base=Sinatra::Base, &block)
10
+ @app = Sinatra.new(base, &block)
11
+ end
12
+
13
+ undef request if method_defined?(:request)
14
+
15
+ def request(verb, path, *args)
16
+ fail "@app not set - cannot make request" if @app.nil?
17
+ @request = Rack::MockRequest.new(@app)
18
+ opts, input =
19
+ case args.size
20
+ when 2 # input, env
21
+ input, env = args
22
+ if input.kind_of?(Hash) # params, env
23
+ [env, param_string(input)]
24
+ else
25
+ [env, input]
26
+ end
27
+ when 1 # params
28
+ if (data = args.first).kind_of?(Hash)
29
+ env = (data.delete(:env) || {})
30
+ [env, param_string(data)]
31
+ else
32
+ [{}, data]
33
+ end
34
+ when 0
35
+ [{}, '']
36
+ else
37
+ raise ArgumentError, "zero, one, or two arguments expected"
38
+ end
39
+ opts = rack_opts(opts)
40
+ opts[:input] ||= input
41
+ yield @request if block_given?
42
+ @response = @request.request(verb, path, opts)
43
+ end
44
+
45
+ def get(path, *args, &b) ; request('GET', path, *args, &b) ; end
46
+ def head(path, *args, &b) ; request('HEAD', path, *args, &b) ; end
47
+ def post(path, *args, &b) ; request('POST', path, *args, &b) ; end
48
+ def put(path, *args, &b) ; request('PUT', path, *args, &b) ; end
49
+ def delete(path, *args, &b) ; request('DELETE', path, *args, &b) ; end
50
+
51
+ def follow!
52
+ request 'GET', @response.location
53
+ end
54
+
55
+ def should
56
+ @response.should
57
+ end
58
+
59
+ def body
60
+ @response.body
61
+ end
62
+
63
+ def status
64
+ @response.status
65
+ end
66
+
67
+ RACK_OPT_NAMES = {
68
+ :accept => "HTTP_ACCEPT",
69
+ :agent => "HTTP_USER_AGENT",
70
+ :host => "HTTP_HOST",
71
+ :session => "HTTP_COOKIE",
72
+ :cookies => "HTTP_COOKIE",
73
+ :content_type => "CONTENT_TYPE"
74
+ }
75
+
76
+ def rack_opts(opts)
77
+ opts.inject({}) do |hash,(key,val)|
78
+ key = RACK_OPT_NAMES[key] || key
79
+ hash[key] = val
80
+ hash
81
+ end
82
+ end
83
+
84
+ def env_for(opts={})
85
+ opts = rack_opts(opts)
86
+ Rack::MockRequest.env_for(opts)
87
+ end
88
+
89
+ def param_string(hash)
90
+ hash.map { |pair| pair.map{|v|escape(v)}.join('=') }.join('&')
91
+ end
92
+
93
+ if defined? Sinatra::Compat
94
+ # Deprecated. Use: "get" instead of "get_it".
95
+ %w(get head post put delete).each do |verb|
96
+ alias_method "#{verb}_it", verb
97
+ remove_method verb
98
+ end
99
+
100
+ include Sinatra::Delegator
101
+
102
+ # Deprecated. Tests no longer delegate missing methods to the
103
+ # mock response. Use: @response
104
+ def method_missing(name, *args, &block)
105
+ if @response && @response.respond_to?(name)
106
+ @response.send(name, *args, &block)
107
+ else
108
+ super
109
+ end
110
+ end
111
+ end
112
+ end
data/lib/sinatra.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'sinatra/base'
2
+ require 'sinatra/main'
3
+ require 'sinatra/compat'
data/sinatra.gemspec ADDED
@@ -0,0 +1,107 @@
1
+ Gem::Specification.new do |s|
2
+ s.specification_version = 2 if s.respond_to? :specification_version=
3
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
+
5
+ s.name = 'sinatra'
6
+ s.version = '0.8.9'
7
+ s.date = '2009-01-13'
8
+
9
+ s.description = "Classy web-development dressed in a DSL"
10
+ s.summary = "Classy web-development dressed in a DSL"
11
+
12
+ s.authors = ["Blake Mizerany"]
13
+
14
+ # = MANIFEST =
15
+ s.files = %w[
16
+ AUTHORS
17
+ CHANGES
18
+ LICENSE
19
+ README.rdoc
20
+ Rakefile
21
+ compat/app_test.rb
22
+ compat/application_test.rb
23
+ compat/builder_test.rb
24
+ compat/custom_error_test.rb
25
+ compat/erb_test.rb
26
+ compat/events_test.rb
27
+ compat/filter_test.rb
28
+ compat/haml_test.rb
29
+ compat/helper.rb
30
+ compat/mapped_error_test.rb
31
+ compat/pipeline_test.rb
32
+ compat/public/foo.xml
33
+ compat/sass_test.rb
34
+ compat/sessions_test.rb
35
+ compat/streaming_test.rb
36
+ compat/sym_params_test.rb
37
+ compat/template_test.rb
38
+ compat/use_in_file_templates_test.rb
39
+ compat/views/foo.builder
40
+ compat/views/foo.erb
41
+ compat/views/foo.haml
42
+ compat/views/foo.sass
43
+ compat/views/foo_layout.erb
44
+ compat/views/foo_layout.haml
45
+ compat/views/layout_test/foo.builder
46
+ compat/views/layout_test/foo.erb
47
+ compat/views/layout_test/foo.haml
48
+ compat/views/layout_test/foo.sass
49
+ compat/views/layout_test/layout.builder
50
+ compat/views/layout_test/layout.erb
51
+ compat/views/layout_test/layout.haml
52
+ compat/views/layout_test/layout.sass
53
+ compat/views/no_layout/no_layout.builder
54
+ compat/views/no_layout/no_layout.haml
55
+ lib/sinatra.rb
56
+ lib/sinatra/base.rb
57
+ lib/sinatra/compat.rb
58
+ lib/sinatra/images/404.png
59
+ lib/sinatra/images/500.png
60
+ lib/sinatra/main.rb
61
+ lib/sinatra/test.rb
62
+ lib/sinatra/test/rspec.rb
63
+ lib/sinatra/test/spec.rb
64
+ lib/sinatra/test/unit.rb
65
+ sinatra.gemspec
66
+ test/base_test.rb
67
+ test/builder_test.rb
68
+ test/data/reload_app_file.rb
69
+ test/erb_test.rb
70
+ test/filter_test.rb
71
+ test/haml_test.rb
72
+ test/helpers_test.rb
73
+ test/mapped_error_test.rb
74
+ test/middleware_test.rb
75
+ test/options_test.rb
76
+ test/reload_test.rb
77
+ test/request_test.rb
78
+ test/result_test.rb
79
+ test/routing_test.rb
80
+ test/sass_test.rb
81
+ test/sinatra_test.rb
82
+ test/static_test.rb
83
+ test/templates_test.rb
84
+ test/views/hello.builder
85
+ test/views/hello.erb
86
+ test/views/hello.haml
87
+ test/views/hello.sass
88
+ test/views/hello.test
89
+ test/views/layout2.builder
90
+ test/views/layout2.erb
91
+ test/views/layout2.haml
92
+ test/views/layout2.test
93
+ ]
94
+ # = MANIFEST =
95
+
96
+ s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
97
+
98
+ s.extra_rdoc_files = %w[README.rdoc LICENSE]
99
+ s.add_dependency 'rack', '>= 0.9.0'
100
+
101
+ s.has_rdoc = true
102
+ s.homepage = "http://sinatra.rubyforge.org"
103
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Sinatra", "--main", "README.rdoc"]
104
+ s.require_paths = %w[lib]
105
+ s.rubyforge_project = 'sinatra'
106
+ s.rubygems_version = '1.1.1'
107
+ end
data/test/base_test.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'test/spec'
2
+ require 'sinatra/base'
3
+ require 'sinatra/test'
4
+
5
+ describe 'Sinatra::Base' do
6
+ include Sinatra::Test
7
+
8
+ it 'includes Rack::Utils' do
9
+ Sinatra::Base.should.include Rack::Utils
10
+ end
11
+
12
+ it 'can be used as a Rack application' do
13
+ mock_app {
14
+ get '/' do
15
+ 'Hello World'
16
+ end
17
+ }
18
+ @app.should.respond_to :call
19
+
20
+ request = Rack::MockRequest.new(@app)
21
+ response = request.get('/')
22
+ response.should.be.ok
23
+ response.body.should.equal 'Hello World'
24
+ end
25
+
26
+ it 'can be used as Rack middleware' do
27
+ app = lambda { |env| [200, {}, ['Goodbye World']] }
28
+ mock_middleware =
29
+ mock_app {
30
+ get '/' do
31
+ 'Hello World'
32
+ end
33
+ get '/goodbye' do
34
+ @app.call(request.env)
35
+ end
36
+ }
37
+ middleware = mock_middleware.new(app)
38
+ middleware.app.should.be app
39
+
40
+ request = Rack::MockRequest.new(middleware)
41
+ response = request.get('/')
42
+ response.should.be.ok
43
+ response.body.should.equal 'Hello World'
44
+
45
+ response = request.get('/goodbye')
46
+ response.should.be.ok
47
+ response.body.should.equal 'Goodbye World'
48
+ end
49
+
50
+ it 'can take multiple definitions of a route' do
51
+ app = mock_app {
52
+ user_agent(/Foo/)
53
+ get '/foo' do
54
+ 'foo'
55
+ end
56
+
57
+ get '/foo' do
58
+ 'not foo'
59
+ end
60
+ }
61
+
62
+ request = Rack::MockRequest.new(app)
63
+ response = request.get('/foo', 'HTTP_USER_AGENT' => 'Foo')
64
+ response.should.be.ok
65
+ response.body.should.equal 'foo'
66
+
67
+ request = Rack::MockRequest.new(app)
68
+ response = request.get('/foo')
69
+ response.should.be.ok
70
+ response.body.should.equal 'not foo'
71
+ end
72
+ end
@@ -0,0 +1,68 @@
1
+ require 'test/spec'
2
+ require 'sinatra/base'
3
+ require 'sinatra/test'
4
+
5
+ describe "Builder Templates" do
6
+ include Sinatra::Test
7
+
8
+ def builder_app(&block)
9
+ mock_app {
10
+ set :views, File.dirname(__FILE__) + '/views'
11
+ get '/', &block
12
+ }
13
+ get '/'
14
+ end
15
+
16
+ it 'renders inline Builder strings' do
17
+ builder_app { builder 'xml.instruct!' }
18
+ should.be.ok
19
+ body.should.equal %{<?xml version="1.0" encoding="UTF-8"?>\n}
20
+ end
21
+
22
+ it 'renders inline blocks' do
23
+ builder_app {
24
+ @name = "Frank & Mary"
25
+ builder do |xml|
26
+ xml.couple @name
27
+ end
28
+ }
29
+ should.be.ok
30
+ body.should.equal "<couple>Frank &amp; Mary</couple>\n"
31
+ end
32
+
33
+ it 'renders .builder files in views path' do
34
+ builder_app {
35
+ @name = "Blue"
36
+ builder :hello
37
+ }
38
+ should.be.ok
39
+ body.should.equal %(<exclaim>You're my boy, Blue!</exclaim>\n)
40
+ end
41
+
42
+ it "renders with inline layouts" do
43
+ mock_app {
44
+ layout do
45
+ %(xml.layout { xml << yield })
46
+ end
47
+ get('/') { builder %(xml.em 'Hello World') }
48
+ }
49
+ get '/'
50
+ should.be.ok
51
+ body.should.equal "<layout>\n<em>Hello World</em>\n</layout>\n"
52
+ end
53
+
54
+ it "renders with file layouts" do
55
+ builder_app {
56
+ builder %(xml.em 'Hello World'), :layout => :layout2
57
+ }
58
+ should.be.ok
59
+ body.should.equal "<layout>\n<em>Hello World</em>\n</layout>\n"
60
+ end
61
+
62
+ it "raises error if template not found" do
63
+ mock_app {
64
+ get('/') { builder :no_such_template }
65
+ }
66
+ lambda { get('/') }.should.raise(Errno::ENOENT)
67
+ end
68
+ end
@@ -0,0 +1,3 @@
1
+ $reload_count += 1
2
+
3
+ $reload_app.get('/') { 'Hello from reload file' }