roda 3.28.0 → 3.29.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +10 -0
  3. data/README.rdoc +10 -0
  4. data/doc/release_notes/3.29.0.txt +15 -0
  5. data/lib/roda.rb +1 -0
  6. data/lib/roda/plugins/caching.rb +2 -0
  7. data/lib/roda/plugins/common_logger.rb +1 -1
  8. data/lib/roda/plugins/exception_page.rb +7 -1
  9. data/lib/roda/plugins/indifferent_params.rb +2 -0
  10. data/lib/roda/version.rb +1 -1
  11. metadata +4 -214
  12. data/Rakefile +0 -108
  13. data/doc/release_notes/1.0.0.txt +0 -329
  14. data/doc/release_notes/1.1.0.txt +0 -226
  15. data/doc/release_notes/1.2.0.txt +0 -406
  16. data/doc/release_notes/1.3.0.txt +0 -109
  17. data/doc/release_notes/2.0.0.txt +0 -75
  18. data/doc/release_notes/2.1.0.txt +0 -124
  19. data/doc/release_notes/2.10.0.txt +0 -27
  20. data/doc/release_notes/2.11.0.txt +0 -70
  21. data/doc/release_notes/2.12.0.txt +0 -40
  22. data/doc/release_notes/2.13.0.txt +0 -10
  23. data/doc/release_notes/2.14.0.txt +0 -44
  24. data/doc/release_notes/2.15.0.txt +0 -53
  25. data/doc/release_notes/2.16.0.txt +0 -48
  26. data/doc/release_notes/2.17.0.txt +0 -62
  27. data/doc/release_notes/2.18.0.txt +0 -69
  28. data/doc/release_notes/2.19.0.txt +0 -30
  29. data/doc/release_notes/2.2.0.txt +0 -97
  30. data/doc/release_notes/2.20.0.txt +0 -5
  31. data/doc/release_notes/2.21.0.txt +0 -17
  32. data/doc/release_notes/2.22.0.txt +0 -41
  33. data/doc/release_notes/2.23.0.txt +0 -29
  34. data/doc/release_notes/2.24.0.txt +0 -65
  35. data/doc/release_notes/2.25.0.txt +0 -14
  36. data/doc/release_notes/2.26.0.txt +0 -13
  37. data/doc/release_notes/2.27.0.txt +0 -56
  38. data/doc/release_notes/2.28.0.txt +0 -17
  39. data/doc/release_notes/2.29.0.txt +0 -156
  40. data/doc/release_notes/2.3.0.txt +0 -109
  41. data/doc/release_notes/2.4.0.txt +0 -55
  42. data/doc/release_notes/2.5.0.txt +0 -23
  43. data/doc/release_notes/2.5.1.txt +0 -4
  44. data/doc/release_notes/2.6.0.txt +0 -21
  45. data/doc/release_notes/2.7.0.txt +0 -75
  46. data/doc/release_notes/2.8.0.txt +0 -44
  47. data/doc/release_notes/2.9.0.txt +0 -6
  48. data/spec/all.rb +0 -1
  49. data/spec/assets/css/app.scss +0 -1
  50. data/spec/assets/css/no_access.css +0 -1
  51. data/spec/assets/css/raw.css +0 -1
  52. data/spec/assets/js/head/app.js +0 -1
  53. data/spec/composition_spec.rb +0 -31
  54. data/spec/define_roda_method_spec.rb +0 -274
  55. data/spec/env_spec.rb +0 -11
  56. data/spec/freeze_spec.rb +0 -37
  57. data/spec/integration_spec.rb +0 -209
  58. data/spec/matchers_spec.rb +0 -832
  59. data/spec/opts_spec.rb +0 -42
  60. data/spec/plugin/_after_hook_spec.rb +0 -19
  61. data/spec/plugin/all_verbs_spec.rb +0 -29
  62. data/spec/plugin/assets_preloading_spec.rb +0 -98
  63. data/spec/plugin/assets_spec.rb +0 -745
  64. data/spec/plugin/backtracking_array_spec.rb +0 -42
  65. data/spec/plugin/branch_locals_spec.rb +0 -106
  66. data/spec/plugin/caching_spec.rb +0 -337
  67. data/spec/plugin/chunked_spec.rb +0 -201
  68. data/spec/plugin/class_level_routing_spec.rb +0 -164
  69. data/spec/plugin/class_matchers_spec.rb +0 -40
  70. data/spec/plugin/common_logger_spec.rb +0 -85
  71. data/spec/plugin/content_for_spec.rb +0 -162
  72. data/spec/plugin/content_security_policy_spec.rb +0 -175
  73. data/spec/plugin/cookies_spec.rb +0 -51
  74. data/spec/plugin/csrf_spec.rb +0 -111
  75. data/spec/plugin/default_headers_spec.rb +0 -82
  76. data/spec/plugin/default_status_spec.rb +0 -95
  77. data/spec/plugin/delay_build_spec.rb +0 -23
  78. data/spec/plugin/delegate_spec.rb +0 -23
  79. data/spec/plugin/delete_empty_headers_spec.rb +0 -27
  80. data/spec/plugin/direct_call_spec.rb +0 -28
  81. data/spec/plugin/disallow_file_uploads_spec.rb +0 -25
  82. data/spec/plugin/drop_body_spec.rb +0 -24
  83. data/spec/plugin/early_hints_spec.rb +0 -19
  84. data/spec/plugin/empty_root_spec.rb +0 -14
  85. data/spec/plugin/environments_spec.rb +0 -42
  86. data/spec/plugin/error_email_spec.rb +0 -97
  87. data/spec/plugin/error_handler_spec.rb +0 -216
  88. data/spec/plugin/error_mail_spec.rb +0 -93
  89. data/spec/plugin/exception_page_spec.rb +0 -168
  90. data/spec/plugin/flash_spec.rb +0 -121
  91. data/spec/plugin/h_spec.rb +0 -11
  92. data/spec/plugin/halt_spec.rb +0 -119
  93. data/spec/plugin/hash_matcher_spec.rb +0 -27
  94. data/spec/plugin/hash_routes_spec.rb +0 -535
  95. data/spec/plugin/head_spec.rb +0 -52
  96. data/spec/plugin/header_matchers_spec.rb +0 -98
  97. data/spec/plugin/heartbeat_spec.rb +0 -74
  98. data/spec/plugin/hooks_spec.rb +0 -152
  99. data/spec/plugin/indifferent_params_spec.rb +0 -14
  100. data/spec/plugin/json_parser_spec.rb +0 -141
  101. data/spec/plugin/json_spec.rb +0 -83
  102. data/spec/plugin/mail_processor_spec.rb +0 -451
  103. data/spec/plugin/mailer_spec.rb +0 -282
  104. data/spec/plugin/match_affix_spec.rb +0 -43
  105. data/spec/plugin/match_hook_spec.rb +0 -79
  106. data/spec/plugin/middleware_spec.rb +0 -237
  107. data/spec/plugin/middleware_stack_spec.rb +0 -81
  108. data/spec/plugin/module_include_spec.rb +0 -48
  109. data/spec/plugin/multi_route_spec.rb +0 -268
  110. data/spec/plugin/multi_run_spec.rb +0 -87
  111. data/spec/plugin/multi_view_spec.rb +0 -50
  112. data/spec/plugin/multibyte_string_matcher_spec.rb +0 -44
  113. data/spec/plugin/named_templates_spec.rb +0 -96
  114. data/spec/plugin/not_allowed_spec.rb +0 -69
  115. data/spec/plugin/not_found_spec.rb +0 -128
  116. data/spec/plugin/optimized_string_matchers_spec.rb +0 -43
  117. data/spec/plugin/padrino_render_spec.rb +0 -34
  118. data/spec/plugin/param_matchers_spec.rb +0 -69
  119. data/spec/plugin/params_capturing_spec.rb +0 -33
  120. data/spec/plugin/partials_spec.rb +0 -43
  121. data/spec/plugin/pass_spec.rb +0 -29
  122. data/spec/plugin/path_matchers_spec.rb +0 -42
  123. data/spec/plugin/path_rewriter_spec.rb +0 -45
  124. data/spec/plugin/path_spec.rb +0 -222
  125. data/spec/plugin/placeholder_string_matchers_spec.rb +0 -126
  126. data/spec/plugin/precompile_templates_spec.rb +0 -61
  127. data/spec/plugin/public_spec.rb +0 -85
  128. data/spec/plugin/render_each_spec.rb +0 -82
  129. data/spec/plugin/render_locals_spec.rb +0 -114
  130. data/spec/plugin/render_spec.rb +0 -912
  131. data/spec/plugin/request_aref_spec.rb +0 -51
  132. data/spec/plugin/request_headers_spec.rb +0 -39
  133. data/spec/plugin/response_request_spec.rb +0 -43
  134. data/spec/plugin/route_block_args_spec.rb +0 -86
  135. data/spec/plugin/route_csrf_spec.rb +0 -305
  136. data/spec/plugin/run_append_slash_spec.rb +0 -77
  137. data/spec/plugin/run_handler_spec.rb +0 -53
  138. data/spec/plugin/sessions_spec.rb +0 -452
  139. data/spec/plugin/shared_vars_spec.rb +0 -45
  140. data/spec/plugin/sinatra_helpers_spec.rb +0 -537
  141. data/spec/plugin/slash_path_empty_spec.rb +0 -22
  142. data/spec/plugin/static_routing_spec.rb +0 -192
  143. data/spec/plugin/static_spec.rb +0 -30
  144. data/spec/plugin/status_303_spec.rb +0 -28
  145. data/spec/plugin/status_handler_spec.rb +0 -158
  146. data/spec/plugin/streaming_spec.rb +0 -246
  147. data/spec/plugin/strip_path_prefix_spec.rb +0 -24
  148. data/spec/plugin/symbol_matchers_spec.rb +0 -51
  149. data/spec/plugin/symbol_status_spec.rb +0 -25
  150. data/spec/plugin/symbol_views_spec.rb +0 -32
  151. data/spec/plugin/timestamp_public_spec.rb +0 -85
  152. data/spec/plugin/type_routing_spec.rb +0 -348
  153. data/spec/plugin/typecast_params_spec.rb +0 -1370
  154. data/spec/plugin/unescape_path_spec.rb +0 -22
  155. data/spec/plugin/view_options_spec.rb +0 -170
  156. data/spec/plugin_spec.rb +0 -71
  157. data/spec/redirect_spec.rb +0 -41
  158. data/spec/request_spec.rb +0 -97
  159. data/spec/response_spec.rb +0 -199
  160. data/spec/route_spec.rb +0 -39
  161. data/spec/session_middleware_spec.rb +0 -129
  162. data/spec/session_spec.rb +0 -37
  163. data/spec/spec_helper.rb +0 -137
  164. data/spec/version_spec.rb +0 -14
  165. data/spec/views/_test.erb +0 -1
  166. data/spec/views/a.erb +0 -1
  167. data/spec/views/a.rdoc +0 -2
  168. data/spec/views/about.erb +0 -1
  169. data/spec/views/about.str +0 -1
  170. data/spec/views/about/_test.css.gz +0 -0
  171. data/spec/views/about/_test.erb +0 -1
  172. data/spec/views/about/_test.erb.gz +0 -0
  173. data/spec/views/about/comp_test.erb +0 -1
  174. data/spec/views/b.erb +0 -1
  175. data/spec/views/c.erb +0 -1
  176. data/spec/views/comp_layout.erb +0 -1
  177. data/spec/views/comp_test.erb +0 -1
  178. data/spec/views/content-yield.erb +0 -1
  179. data/spec/views/each.str +0 -1
  180. data/spec/views/home.erb +0 -2
  181. data/spec/views/home.str +0 -2
  182. data/spec/views/iv.erb +0 -1
  183. data/spec/views/layout-alternative.erb +0 -2
  184. data/spec/views/layout-yield.erb +0 -3
  185. data/spec/views/layout.erb +0 -2
  186. data/spec/views/layout.str +0 -2
  187. data/spec/views/multiple-layout.erb +0 -1
  188. data/spec/views/multiple.erb +0 -1
@@ -1,45 +0,0 @@
1
- require_relative "../spec_helper"
2
-
3
- describe "shared_vars plugin" do
4
- it "adds shared method for sharing variables across multiple apps" do
5
- app(:shared_vars) {|r| shared[:c]}
6
- old_app = app
7
- app(:shared_vars) do |r|
8
- shared[:c] = 'c'
9
- r.run old_app
10
- end
11
-
12
- body.must_equal 'c'
13
- end
14
-
15
- it "adds shared with hash merges the hash into the shared vars" do
16
- app(:shared_vars) do |r|
17
- shared(:c=>'c')
18
- shared[:c]
19
- end
20
-
21
- body.must_equal 'c'
22
- end
23
-
24
- it "calling shared with hash and a block sets shared variables only for that block" do
25
- app(:shared_vars) do |r|
26
- c = nil
27
- d = nil
28
- shared[:c] = 'b'
29
- shared(:c=>'c', :d=>'d') do
30
- c = shared[:c]
31
- d = shared[:d]
32
- end
33
- "#{shared[:c]}:#{shared[:d]}:#{c}:#{d}"
34
- end
35
-
36
- body.must_equal 'b::c:d'
37
- end
38
-
39
- it "calling shared with no arguments and a block raises an error" do
40
- app(:shared_vars) do |r|
41
- shared{}
42
- end
43
- proc{body}.must_raise(Roda::RodaError)
44
- end
45
- end
@@ -1,537 +0,0 @@
1
- require_relative "../spec_helper"
2
-
3
- require 'uri'
4
-
5
- describe "sinatra_helpers plugin" do
6
- def sin_app(&block)
7
- app(:sinatra_helpers, &block)
8
- end
9
-
10
- def status_app(code, &block)
11
- block ||= proc{}
12
- sin_app do |r|
13
- status code
14
- instance_eval(&block).inspect
15
- end
16
- end
17
-
18
- it 'status returns the response status code if not given an argument' do
19
- status_app(207){status}
20
- body.must_equal "207"
21
- end
22
-
23
- it 'status sets the response status code if given an argument' do
24
- status_app 207
25
- status.must_equal 207
26
- end
27
-
28
- it 'not_found? is true only if status == 404' do
29
- status_app(404){not_found?}
30
- body.must_equal 'true'
31
- status_app(405){not_found?}
32
- body.must_equal 'false'
33
- status_app(403){not_found?}
34
- body.must_equal 'false'
35
- end
36
-
37
- it 'informational? is true only for 1xx status' do
38
- status_app(100 + rand(100)){informational?}
39
- body.must_equal 'true'
40
- status_app(200 + rand(400)){informational?}
41
- body.must_equal 'false'
42
- end
43
-
44
- it 'success? is true only for 2xx status' do
45
- status_app(200 + rand(100)){success?}
46
- body.must_equal 'true'
47
- status_app(100 + rand(100)){success?}
48
- body.must_equal 'false'
49
- status_app(300 + rand(300)){success?}
50
- body.must_equal 'false'
51
- end
52
-
53
- it 'redirect? is true only for 3xx status' do
54
- status_app(300 + rand(100)){redirect?}
55
- body.must_equal 'true'
56
- status_app(200 + rand(100)){redirect?}
57
- body.must_equal 'false'
58
- status_app(400 + rand(200)){redirect?}
59
- body.must_equal 'false'
60
- end
61
-
62
- it 'client_error? is true only for 4xx status' do
63
- status_app(400 + rand(100)){client_error?}
64
- body.must_equal 'true'
65
- status_app(200 + rand(200)){client_error?}
66
- body.must_equal 'false'
67
- status_app(500 + rand(100)){client_error?}
68
- body.must_equal 'false'
69
- end
70
-
71
- it 'server_error? is true only for 5xx status' do
72
- status_app(500 + rand(100)){server_error?}
73
- body.must_equal 'true'
74
- status_app(200 + rand(300)){server_error?}
75
- body.must_equal 'false'
76
- end
77
-
78
- describe 'body' do
79
- it 'takes a block for deferred body generation' do
80
- sin_app{body{'Hello World'}; nil}
81
- body.must_equal 'Hello World'
82
- header('Content-Length').must_equal '11'
83
- end
84
-
85
- it 'supports #join' do
86
- sin_app{body{'Hello World'}; nil}
87
- req[2].join.must_equal 'Hello World'
88
- end
89
-
90
- it 'takes a String, Array, or other object responding to #each' do
91
- sin_app{body 'Hello World'; nil}
92
- body.must_equal 'Hello World'
93
- header('Content-Length').must_equal '11'
94
-
95
- sin_app{body ['Hello ', 'World']; nil}
96
- body.must_equal 'Hello World'
97
- header('Content-Length').must_equal '11'
98
-
99
- o = Object.new
100
- def o.each; yield 'Hello World' end
101
- sin_app{body o; nil}
102
- body.must_equal 'Hello World'
103
- header('Content-Length').must_equal '11'
104
- end
105
- end
106
-
107
- describe 'redirect' do
108
- it 'uses a 302 when only a path is given' do
109
- sin_app do
110
- redirect '/foo'
111
- fail 'redirect should halt'
112
- end
113
-
114
- status.must_equal 302
115
- body.must_equal ''
116
- header('Location').must_equal '/foo'
117
- end
118
-
119
- it 'adds script_name if given a path' do
120
- sin_app{redirect "/foo"}
121
- header('Location', '/bar', 'SCRIPT_NAME'=>'/foo').must_equal '/foo'
122
- end
123
-
124
- it 'does not adds script_name if not given a path' do
125
- sin_app{redirect}
126
- header('Location', '/bar', 'SCRIPT_NAME'=>'/foo', 'REQUEST_METHOD'=>'POST').must_equal '/foo/bar'
127
- end
128
-
129
- it 'respects :absolute_redirects option' do
130
- sin_app{redirect}
131
- app.opts[:absolute_redirects] = true
132
- header('Location', '/bar', 'HTTP_HOST'=>'example.org', 'SCRIPT_NAME'=>'/foo', 'REQUEST_METHOD'=>'POST').must_equal 'http://example.org/foo/bar'
133
- end
134
-
135
- it 'respects :prefixed_redirects option' do
136
- sin_app{redirect "/bar"}
137
- app.opts[:prefixed_redirects] = true
138
- header('Location', 'SCRIPT_NAME'=>'/foo').must_equal '/foo/bar'
139
- end
140
-
141
- it 'ignores :prefix_redirects option if not given a path' do
142
- sin_app{redirect}
143
- app.opts[:prefix_redirects] = true
144
- header('Location', "/bar", 'SCRIPT_NAME'=>'/foo', 'REQUEST_METHOD'=>'POST').must_equal '/foo/bar'
145
- end
146
-
147
- it 'uses the code given when specified' do
148
- sin_app{redirect '/foo', 301}
149
- status.must_equal 301
150
- end
151
-
152
- it 'redirects back to request.referer when passed back' do
153
- sin_app{redirect back}
154
- header('Location', 'HTTP_REFERER' => '/foo').must_equal '/foo'
155
- end
156
-
157
- it 'uses 303 for post requests if request is HTTP 1.1, 302 for 1.0' do
158
- sin_app{redirect '/foo'}
159
- status('HTTP_VERSION' => 'HTTP/1.1', 'REQUEST_METHOD'=>'POST').must_equal 303
160
- status('HTTP_VERSION' => 'HTTP/1.0', 'REQUEST_METHOD'=>'POST').must_equal 302
161
- end
162
- end
163
-
164
- describe 'error' do
165
- it 'sets a status code and halts' do
166
- sin_app do
167
- error
168
- fail 'error should halt'
169
- end
170
-
171
- status.must_equal 500
172
- body.must_equal ''
173
- end
174
-
175
- it 'accepts status code' do
176
- sin_app{error 501}
177
- status.must_equal 501
178
- body.must_equal ''
179
- end
180
-
181
- it 'accepts body' do
182
- sin_app{error '501'}
183
- status.must_equal 500
184
- body.must_equal '501'
185
- end
186
-
187
- it 'accepts status code and body' do
188
- sin_app{error 502, '501'}
189
- status.must_equal 502
190
- body.must_equal '501'
191
- end
192
- end
193
-
194
- describe 'not_found' do
195
- it 'halts with a 404 status' do
196
- sin_app do
197
- not_found
198
- fail 'not_found should halt'
199
- end
200
-
201
- status.must_equal 404
202
- body.must_equal ''
203
- end
204
-
205
- it 'accepts optional body' do
206
- sin_app{not_found 'nf'}
207
- status.must_equal 404
208
- body.must_equal 'nf'
209
- end
210
- end
211
-
212
- describe 'headers' do
213
- it 'sets headers on the response object when given a Hash' do
214
- sin_app do
215
- headers 'X-Foo' => 'bar'
216
- 'kthx'
217
- end
218
-
219
- header('X-Foo').must_equal 'bar'
220
- body.must_equal 'kthx'
221
- end
222
-
223
- it 'returns the response headers hash when no hash provided' do
224
- sin_app{headers['X-Foo'] = 'bar'}
225
- header('X-Foo').must_equal 'bar'
226
- end
227
- end
228
-
229
- describe 'mime_type' do
230
- before do
231
- sin_app{|r| mime_type((r.path unless r.path.empty?)).to_s}
232
- end
233
-
234
- it "looks up mime types in Rack's MIME registry" do
235
- Rack::Mime::MIME_TYPES['.foo'] = 'application/foo'
236
- body('foo').must_equal 'application/foo'
237
- body('.foo').must_equal 'application/foo'
238
- end
239
-
240
- it 'returns nil when given nil' do
241
- body('PATH_INFO'=>'').must_equal ''
242
- end
243
-
244
- it 'returns nil when media type not registered' do
245
- body('bizzle').must_equal ''
246
- end
247
-
248
- it 'returns the argument when given a media type string' do
249
- body('text/plain').must_equal 'text/plain'
250
- end
251
-
252
- it 'supports mime types registered at the class level' do
253
- app.mime_type :foo, 'application/foo2'
254
- body('foo').must_equal 'application/foo2'
255
- end
256
- end
257
-
258
- describe 'content_type' do
259
- it 'sets the Content-Type header' do
260
- sin_app do
261
- content_type 'text/plain'
262
- 'Hello World'
263
- end
264
-
265
- header('Content-Type').must_equal 'text/plain'
266
- body.must_equal 'Hello World'
267
- end
268
-
269
- it 'takes media type parameters (like charset=)' do
270
- sin_app{content_type 'text/html', :charset => 'latin1'}
271
- header('Content-Type').must_equal 'text/html;charset=latin1'
272
- end
273
-
274
- it "looks up symbols in Rack's mime types dictionary" do
275
- sin_app{content_type :foo}
276
- Rack::Mime::MIME_TYPES['.foo'] = 'application/foo'
277
- header('Content-Type').must_equal 'application/foo'
278
- end
279
-
280
- it 'fails when no mime type is registered for the argument provided' do
281
- sin_app{content_type :bizzle}
282
- proc{body}.must_raise(Roda::RodaError)
283
- end
284
-
285
- it 'handles already present params' do
286
- sin_app{content_type 'foo/bar;level=1', :charset => 'utf-8'}
287
- header('Content-Type').must_equal 'foo/bar;level=1, charset=utf-8'
288
- end
289
-
290
- it 'does not add charset if present' do
291
- sin_app{content_type 'text/plain;charset=utf-16', :charset => 'utf-8'}
292
- header('Content-Type').must_equal 'text/plain;charset=utf-16'
293
- end
294
-
295
- it 'properly encodes parameters with delimiter characters' do
296
- sin_app{|r| content_type 'image/png', :comment => r.path }
297
- header('Content-Type', 'Hello, world!').must_equal 'image/png;comment="Hello, world!"'
298
- header('Content-Type', 'semi;colon').must_equal 'image/png;comment="semi;colon"'
299
- header('Content-Type', '"Whatever."').must_equal 'image/png;comment="\"Whatever.\""'
300
- end
301
- end
302
-
303
- describe 'attachment' do
304
- before do
305
- sin_app{|r| attachment r.path; 'b'}
306
- end
307
-
308
- it 'sets the Content-Disposition header' do
309
- header('Content-Disposition', '/foo/test.xml').must_equal 'attachment; filename="test.xml"'
310
- body.must_equal 'b'
311
- end
312
-
313
- it 'sets the Content-Disposition header even when a filename is not given' do
314
- sin_app{attachment}
315
- header('Content-Disposition', '/foo/test.xml').must_equal 'attachment'
316
- end
317
-
318
- it 'sets the Content-Type header' do
319
- header('Content-Type', 'test.xml').must_equal 'application/xml'
320
- end
321
-
322
- it 'does not modify the default Content-Type without a file extension' do
323
- header('Content-Type', 'README').must_equal 'text/html'
324
- end
325
-
326
- it 'should not modify the Content-Type if it is already set' do
327
- sin_app do
328
- content_type :atom
329
- attachment 'test.xml'
330
- end
331
-
332
- header('Content-Type', 'README').must_equal 'application/atom+xml'
333
- end
334
- end
335
-
336
- describe 'send_file' do
337
- before(:all) do
338
- file = @file = 'spec/assets/css/raw.css'
339
- @content = File.read(@file)
340
- sin_app{send_file file, env['OPTS'] || {}}
341
- end
342
-
343
- it "sends the contents of the file" do
344
- status.must_equal 200
345
- body.must_equal @content
346
- end
347
-
348
- it 'sets the Content-Type response header if a mime-type can be located' do
349
- header('Content-Type').must_equal 'text/css'
350
- end
351
-
352
- it 'sets the Content-Type response header if type option is set to a file extension' do
353
- header('Content-Type', 'OPTS'=>{:type => 'html'}).must_equal 'text/html'
354
- end
355
-
356
- it 'sets the Content-Type response header if type option is set to a mime type' do
357
- header('Content-Type', 'OPTS'=>{:type => 'application/octet-stream'}).must_equal 'application/octet-stream'
358
- end
359
-
360
- it 'sets the Content-Length response header' do
361
- header('Content-Length').must_equal @content.length.to_s
362
- end
363
-
364
- it 'sets the Last-Modified response header' do
365
- header('Last-Modified').must_equal File.mtime(@file).httpdate
366
- end
367
-
368
- it 'allows passing in a different Last-Modified response header with :last_modified' do
369
- time = Time.now
370
- @app.plugin :caching
371
- header('Last-Modified', 'OPTS'=>{:last_modified => time}).must_equal time.httpdate
372
- end
373
-
374
- it "returns a 404 when not found" do
375
- sin_app{send_file 'this-file-does-not-exist.txt'}
376
- status.must_equal 404
377
- end
378
-
379
- it "does not set the Content-Disposition header by default" do
380
- header('Content-Disposition').must_be_nil
381
- end
382
-
383
- it "sets the Content-Disposition header when :disposition set to 'attachment'" do
384
- header('Content-Disposition', 'OPTS'=>{:disposition => 'attachment'}).must_equal 'attachment; filename="raw.css"'
385
- end
386
-
387
- it "does not set add a file name if filename is false" do
388
- header('Content-Disposition', 'OPTS'=>{:disposition => 'inline', :filename=>false}).must_equal 'inline'
389
- end
390
-
391
- it "sets the Content-Disposition header when :disposition set to 'inline'" do
392
- header('Content-Disposition', 'OPTS'=>{:disposition => 'inline'}).must_equal 'inline; filename="raw.css"'
393
- end
394
-
395
- it "sets the Content-Disposition header when :filename provided" do
396
- header('Content-Disposition', 'OPTS'=>{:filename => 'foo.txt'}).must_equal 'attachment; filename="foo.txt"'
397
- end
398
-
399
- it 'allows setting a custom status code' do
400
- status('OPTS'=>{:status=>201}).must_equal 201
401
- end
402
-
403
- it "is able to send files with unknown mime type" do
404
- header('Content-Type', 'OPTS'=>{:type => '.foobar'}).must_equal 'application/octet-stream'
405
- end
406
-
407
- it "does not override Content-Type if already set and no explicit type is given" do
408
- file = @file
409
- sin_app do
410
- content_type :png
411
- send_file file
412
- end
413
- header('Content-Type').must_equal 'image/png'
414
- end
415
-
416
- it "does override Content-Type even if already set, if explicit type is given" do
417
- file = @file
418
- sin_app do
419
- content_type :png
420
- send_file file, :type => :gif
421
- end
422
- header('Content-Type').must_equal 'image/gif'
423
- end
424
- end
425
-
426
- describe 'uri' do
427
- describe "without arguments" do
428
- before do
429
- sin_app{uri}
430
- end
431
-
432
- it 'generates absolute urls' do
433
- body('HTTP_HOST'=>'example.org').must_equal 'http://example.org/'
434
- end
435
-
436
- it 'includes path_info' do
437
- body('/foo', 'HTTP_HOST'=>'example.org').must_equal 'http://example.org/foo'
438
- end
439
-
440
- it 'includes script_name' do
441
- body('/bar', 'HTTP_HOST'=>'example.org', "SCRIPT_NAME" => '/foo').must_equal 'http://example.org/foo/bar'
442
- end
443
-
444
- it 'handles standard HTTP and HTTPS ports' do
445
- body('SERVER_NAME'=>'example.org', 'SERVER_PORT' => '80').must_equal 'http://example.org/'
446
- body('SERVER_NAME'=>'example.org', 'SERVER_PORT' => '443', 'HTTPS'=>'on').must_equal 'https://example.org/'
447
- end
448
-
449
- it 'handles non-standard HTTP port' do
450
- body('SERVER_NAME'=>'example.org', 'SERVER_PORT' => '81').must_equal 'http://example.org:81/'
451
- body('SERVER_NAME'=>'example.org', 'SERVER_PORT' => '443').must_equal 'http://example.org:443/'
452
- end
453
-
454
- it 'handles non-standard HTTPS port' do
455
- body('SERVER_NAME'=>'example.org', 'SERVER_PORT' => '444', 'HTTPS'=>'on').must_equal 'https://example.org:444/'
456
- body('SERVER_NAME'=>'example.org', 'SERVER_PORT' => '80', 'HTTPS'=>'on').must_equal 'https://example.org:80/'
457
- end
458
-
459
- it 'handles reverse proxy' do
460
- body('SERVER_NAME'=>'example.org', 'HTTP_X_FORWARDED_HOST' => 'example.com', 'SERVER_PORT' => '8080').must_equal 'http://example.com/'
461
- end
462
- end
463
-
464
- it 'allows passing an alternative to path_info' do
465
- sin_app{uri '/bar'}
466
- body('HTTP_HOST'=>'example.org').must_equal 'http://example.org/bar'
467
- body('HTTP_HOST'=>'example.org', "SCRIPT_NAME" => '/foo').must_equal 'http://example.org/foo/bar'
468
- end
469
-
470
- it 'handles absolute URIs' do
471
- sin_app{uri 'http://google.com'}
472
- body('HTTP_HOST'=>'example.org').must_equal 'http://google.com'
473
- end
474
-
475
- it 'handles different protocols' do
476
- sin_app{uri 'mailto:jsmith@example.com'}
477
- body('HTTP_HOST'=>'example.org').must_equal 'mailto:jsmith@example.com'
478
- end
479
-
480
- it 'allows turning off host' do
481
- sin_app{uri '/foo', false}
482
- body('HTTP_HOST'=>'example.org').must_equal '/foo'
483
- body('HTTP_HOST'=>'example.org', "SCRIPT_NAME" => '/bar').must_equal '/bar/foo'
484
- end
485
-
486
- it 'allows turning off script_name' do
487
- sin_app{uri '/foo', true, false}
488
- body('HTTP_HOST'=>'example.org').must_equal 'http://example.org/foo'
489
- body('HTTP_HOST'=>'example.org', "SCRIPT_NAME" => '/bar').must_equal 'http://example.org/foo'
490
- end
491
-
492
- it 'is aliased to #url' do
493
- sin_app{url}
494
- body('HTTP_HOST'=>'example.org').must_equal 'http://example.org/'
495
- end
496
-
497
- it 'is aliased to #to' do
498
- sin_app{to}
499
- body('HTTP_HOST'=>'example.org').must_equal 'http://example.org/'
500
- end
501
-
502
- it 'accepts a URI object instead of a String' do
503
- sin_app{uri URI.parse('http://roda.jeremyevans.net')}
504
- body.must_equal 'http://roda.jeremyevans.net'
505
- end
506
- end
507
-
508
- it 'logger logs to rack.logger' do
509
- sin_app{logger.info "foo"; nil}
510
- o = Object.new
511
- def o.method_missing(*a)
512
- (@a ||= []) << a
513
- end
514
- def o.logs
515
- @a
516
- end
517
-
518
- status('rack.logger'=>o).must_equal 404
519
- o.logs.must_equal [[:info, 'foo']]
520
- end
521
-
522
- it 'supports disabling delegation if :delegate=>false option is provided' do
523
- app(:bare) do
524
- plugin :sinatra_helpers, :delegate=>false
525
- route do |r|
526
- r.root{content_type}
527
- r.is("req"){r.ssl?.to_s}
528
- r.is("res"){response.not_found?.inspect}
529
- end
530
- end
531
-
532
- proc{body}.must_raise(NameError)
533
- body('/req').must_equal 'false'
534
- body('/res').must_equal 'nil'
535
- end
536
- end
537
-