roda 2.0.0 → 2.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.
- checksums.yaml +4 -4
- data/CHANGELOG +26 -0
- data/README.rdoc +83 -22
- data/Rakefile +1 -1
- data/doc/release_notes/2.1.0.txt +124 -0
- data/lib/roda/plugins/assets.rb +17 -9
- data/lib/roda/plugins/class_level_routing.rb +5 -2
- data/lib/roda/plugins/delegate.rb +6 -3
- data/lib/roda/plugins/indifferent_params.rb +7 -0
- data/lib/roda/plugins/mailer.rb +18 -1
- data/lib/roda/plugins/multi_route.rb +2 -1
- data/lib/roda/plugins/path.rb +75 -6
- data/lib/roda/plugins/render.rb +33 -14
- data/lib/roda/plugins/static.rb +35 -0
- data/lib/roda/plugins/view_options.rb +161 -0
- data/lib/roda/plugins/view_subdirs.rb +6 -63
- data/lib/roda/version.rb +1 -1
- data/spec/composition_spec.rb +12 -0
- data/spec/matchers_spec.rb +34 -0
- data/spec/plugin/assets_spec.rb +112 -17
- data/spec/plugin/delete_empty_headers_spec.rb +12 -0
- data/spec/plugin/mailer_spec.rb +46 -3
- data/spec/plugin/module_include_spec.rb +17 -0
- data/spec/plugin/multi_route_spec.rb +10 -0
- data/spec/plugin/named_templates_spec.rb +6 -0
- data/spec/plugin/not_found_spec.rb +1 -1
- data/spec/plugin/path_spec.rb +76 -0
- data/spec/plugin/render_each_spec.rb +6 -0
- data/spec/plugin/render_spec.rb +40 -1
- data/spec/plugin/sinatra_helpers_spec.rb +5 -0
- data/spec/plugin/static_spec.rb +30 -0
- data/spec/plugin/view_options_spec.rb +117 -0
- data/spec/spec_helper.rb +5 -1
- data/spec/views/multiple-layout.erb +1 -0
- data/spec/views/multiple.erb +1 -0
- metadata +10 -4
- data/spec/plugin/static_path_info_spec.rb +0 -56
- data/spec/plugin/view_subdirs_spec.rb +0 -44
@@ -1,63 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
# automatically use that view subdirectory. Example:
|
8
|
-
#
|
9
|
-
# plugin :render, :layout=>'./layout'
|
10
|
-
# plugin :view_subdirs
|
11
|
-
#
|
12
|
-
# route do |r|
|
13
|
-
# r.on "users" do
|
14
|
-
# set_view_subdir 'users'
|
15
|
-
#
|
16
|
-
# r.get :id do
|
17
|
-
# view 'profile' # uses ./views/users/profile.erb
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# r.get 'list' do
|
21
|
-
# view 'lists/users' # uses ./views/lists/users.erb
|
22
|
-
# end
|
23
|
-
# end
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# Note that when a view subdirectory is set, the layout will
|
27
|
-
# also be looked up in the subdirectory unless it contains
|
28
|
-
# a slash. So if you want to use a view subdirectory for
|
29
|
-
# templates but have a shared layout, you should make sure your
|
30
|
-
# layout contains a slash, similar to the example above.
|
31
|
-
module ViewSubdirs
|
32
|
-
# Load the render plugin before this plugin, since this plugin
|
33
|
-
# works by overriding a method in the render plugin.
|
34
|
-
def self.load_dependencies(app)
|
35
|
-
app.plugin :render
|
36
|
-
end
|
37
|
-
|
38
|
-
module InstanceMethods
|
39
|
-
# Set the view subdirectory to use. This can be set to nil
|
40
|
-
# to not use a view subdirectory.
|
41
|
-
def set_view_subdir(v)
|
42
|
-
@_view_subdir = v
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
# Override the template name to use the view subdirectory if the
|
48
|
-
# there is a view subdirectory and the template name does not
|
49
|
-
# contain a slash.
|
50
|
-
def template_name(opts)
|
51
|
-
name = super
|
52
|
-
if (v = @_view_subdir) && name !~ /\//
|
53
|
-
"#{v}/#{name}"
|
54
|
-
else
|
55
|
-
name
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
register_plugin(:view_subdirs, ViewSubdirs)
|
62
|
-
end
|
63
|
-
end
|
1
|
+
# View options is a superset of the view_subdirs plugin,
|
2
|
+
# which no longer exists. For backwards compatibility,
|
3
|
+
# make attempts to load the view_subdirs plugin load the
|
4
|
+
# view_options plugin instead.
|
5
|
+
require 'roda/plugins/view_options'
|
6
|
+
Roda::RodaPlugins.register_plugin(:view_subdirs, Roda::RodaPlugins::ViewOptions)
|
data/lib/roda/version.rb
CHANGED
data/spec/composition_spec.rb
CHANGED
@@ -16,4 +16,16 @@ describe "r.run" do
|
|
16
16
|
|
17
17
|
body("/provider/services/101").should == 'View 101'
|
18
18
|
end
|
19
|
+
|
20
|
+
it "modifies SCRIPT_NAME/PATH_INFO when calling run" do
|
21
|
+
a = app{|r| "#{r.script_name}|#{r.path_info}"}
|
22
|
+
app(:static_path_info){|r| r.on("a"){r.run a}}
|
23
|
+
body("/a/b").should == "/a|/b"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "restores SCRIPT_NAME/PATH_INFO before returning from run" do
|
27
|
+
a = app{|r| "#{r.script_name}|#{r.path_info}"}
|
28
|
+
app(:static_path_info){|r| s = catch(:halt){r.on("a"){r.run a}}; "#{s[2].join}%#{r.script_name}|#{r.path_info}"}
|
29
|
+
body("/a/b").should == "/a|/b%|/a/b"
|
30
|
+
end
|
19
31
|
end
|
data/spec/matchers_spec.rb
CHANGED
@@ -291,6 +291,40 @@ describe "r.on" do
|
|
291
291
|
body("/123").should == '+1'
|
292
292
|
end
|
293
293
|
|
294
|
+
it "does not modify SCRIPT_NAME/PATH_INFO during routing" do
|
295
|
+
app(:pass) do |r|
|
296
|
+
r.on "foo" do
|
297
|
+
r.is "bar" do
|
298
|
+
"bar|#{env['SCRIPT_NAME']}|#{env['PATH_INFO']}"
|
299
|
+
end
|
300
|
+
r.is "baz" do
|
301
|
+
r.pass
|
302
|
+
end
|
303
|
+
"foo|#{env['SCRIPT_NAME']}|#{env['PATH_INFO']}"
|
304
|
+
end
|
305
|
+
"#{env['SCRIPT_NAME']}|#{env['PATH_INFO']}"
|
306
|
+
end
|
307
|
+
|
308
|
+
body.should == '|/'
|
309
|
+
body('SCRIPT_NAME'=>'/a').should == '/a|/'
|
310
|
+
body('/foo').should == 'foo||/foo'
|
311
|
+
body('/foo', 'SCRIPT_NAME'=>'/a').should == 'foo|/a|/foo'
|
312
|
+
body('/foo/bar').should == 'bar||/foo/bar'
|
313
|
+
body('/foo/bar', 'SCRIPT_NAME'=>'/a').should == 'bar|/a|/foo/bar'
|
314
|
+
body('/foo/baz').should == 'foo||/foo/baz'
|
315
|
+
body('/foo/baz', 'SCRIPT_NAME'=>'/a').should == 'foo|/a|/foo/baz'
|
316
|
+
end
|
317
|
+
|
318
|
+
it "should have path/matched_path/remaining_path work correctly" do
|
319
|
+
app do |r|
|
320
|
+
r.on "foo" do
|
321
|
+
"#{r.path}:#{r.matched_path}:#{r.remaining_path}"
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
body("/foo/bar").should == "/foo/bar:/foo:/bar"
|
326
|
+
end
|
327
|
+
|
294
328
|
it "ensures remaining_path is reverted if modified in failing matcher" do
|
295
329
|
app do |r|
|
296
330
|
r.on lambda { @remaining_path = "/blah"; false } do
|
data/spec/plugin/assets_spec.rb
CHANGED
@@ -11,9 +11,9 @@ rescue LoadError
|
|
11
11
|
end
|
12
12
|
|
13
13
|
if run_tests
|
14
|
-
metadata_file = 'spec/assets/tmp/precompiled.json'
|
15
|
-
js_file = 'spec/assets/js/head/app.js'
|
16
|
-
css_file = 'spec/assets/css/no_access.css'
|
14
|
+
metadata_file = File.expand_path('spec/assets/tmp/precompiled.json')
|
15
|
+
js_file = File.expand_path('spec/assets/js/head/app.js')
|
16
|
+
css_file = File.expand_path('spec/assets/css/no_access.css')
|
17
17
|
js_mtime = File.mtime(js_file)
|
18
18
|
js_atime = File.atime(js_file)
|
19
19
|
css_mtime = File.mtime(css_file)
|
@@ -48,44 +48,58 @@ if run_tests
|
|
48
48
|
end
|
49
49
|
|
50
50
|
it 'assets_opts should use correct paths given options' do
|
51
|
-
|
52
|
-
|
51
|
+
fpaths = [:js_path, :css_path, :compiled_js_path, :compiled_css_path]
|
52
|
+
rpaths = [:js_prefix, :css_prefix, :compiled_js_prefix, :compiled_css_prefix]
|
53
|
+
app.assets_opts.values_at(*fpaths).should == %w"spec/assets/js/ spec/assets/css/ spec/assets/app spec/assets/app".map{|s| File.join(Dir.pwd, s)}
|
54
|
+
app.assets_opts.values_at(*rpaths).should == %w"assets/js/ assets/css/ assets/app assets/app"
|
53
55
|
|
54
56
|
app.plugin :assets, :path=>'bar/', :public=>'foo/', :prefix=>'as/', :js_dir=>'j/', :css_dir=>'c/', :compiled_name=>'a'
|
55
|
-
app.assets_opts.values_at(*
|
57
|
+
app.assets_opts.values_at(*fpaths).should == %w"bar/j/ bar/c/ foo/as/a foo/as/a".map{|s| File.join(Dir.pwd, s)}
|
58
|
+
app.assets_opts.values_at(*rpaths).should == %w"as/j/ as/c/ as/a as/a"
|
56
59
|
|
57
60
|
app.plugin :assets, :path=>'bar', :public=>'foo', :prefix=>'as', :js_dir=>'j', :css_dir=>'c', :compiled_name=>'a'
|
58
|
-
app.assets_opts.values_at(*
|
61
|
+
app.assets_opts.values_at(*fpaths).should == %w"bar/j/ bar/c/ foo/as/a foo/as/a".map{|s| File.join(Dir.pwd, s)}
|
62
|
+
app.assets_opts.values_at(*rpaths).should == %w"as/j/ as/c/ as/a as/a"
|
59
63
|
|
60
64
|
app.plugin :assets, :compiled_js_dir=>'cj', :compiled_css_dir=>'cs', :compiled_path=>'cp'
|
61
|
-
app.assets_opts.values_at(*
|
65
|
+
app.assets_opts.values_at(*fpaths).should == %w"bar/j/ bar/c/ foo/cp/cj/a foo/cp/cs/a".map{|s| File.join(Dir.pwd, s)}
|
66
|
+
app.assets_opts.values_at(*rpaths).should == %w"as/j/ as/c/ as/cj/a as/cs/a"
|
62
67
|
|
63
68
|
app.plugin :assets, :compiled_js_route=>'cjr', :compiled_css_route=>'ccr', :js_route=>'jr', :css_route=>'cr'
|
64
|
-
app.assets_opts.values_at(*
|
69
|
+
app.assets_opts.values_at(*fpaths).should == %w"bar/j/ bar/c/ foo/cp/cj/a foo/cp/cs/a".map{|s| File.join(Dir.pwd, s)}
|
70
|
+
app.assets_opts.values_at(*rpaths).should == %w"as/jr/ as/cr/ as/cjr/a as/ccr/a"
|
65
71
|
|
66
72
|
app.plugin :assets, :compiled_js_route=>'cj', :compiled_css_route=>'cs', :js_route=>'j', :css_route=>'c'
|
67
|
-
app.assets_opts.values_at(*
|
73
|
+
app.assets_opts.values_at(*fpaths).should == %w"bar/j/ bar/c/ foo/cp/cj/a foo/cp/cs/a".map{|s| File.join(Dir.pwd, s)}
|
74
|
+
app.assets_opts.values_at(*rpaths).should == %w"as/j/ as/c/ as/cj/a as/cs/a"
|
68
75
|
|
69
76
|
app.plugin :assets
|
70
|
-
app.assets_opts.values_at(*
|
77
|
+
app.assets_opts.values_at(*fpaths).should == %w"bar/j/ bar/c/ foo/cp/cj/a foo/cp/cs/a".map{|s| File.join(Dir.pwd, s)}
|
78
|
+
app.assets_opts.values_at(*rpaths).should == %w"as/j/ as/c/ as/cj/a as/cs/a"
|
71
79
|
|
72
80
|
app.plugin :assets, :compiled_js_dir=>'', :compiled_css_dir=>nil, :compiled_js_route=>nil, :compiled_css_route=>nil
|
73
|
-
app.assets_opts.values_at(*
|
81
|
+
app.assets_opts.values_at(*fpaths).should == %w"bar/j/ bar/c/ foo/cp/a foo/cp/a".map{|s| File.join(Dir.pwd, s)}
|
82
|
+
app.assets_opts.values_at(*rpaths).should == %w"as/j/ as/c/ as/a as/a"
|
74
83
|
|
75
84
|
app.plugin :assets, :js_dir=>'', :css_dir=>nil, :js_route=>nil, :css_route=>nil
|
76
|
-
app.assets_opts.values_at(*
|
85
|
+
app.assets_opts.values_at(*fpaths).should == %w"bar/ bar/ foo/cp/a foo/cp/a".map{|s| File.join(Dir.pwd, s)}
|
86
|
+
app.assets_opts.values_at(*rpaths).should == %w"as/ as/ as/a as/a"
|
77
87
|
|
78
88
|
app.plugin :assets, :public=>''
|
79
|
-
app.assets_opts.values_at(*
|
89
|
+
app.assets_opts.values_at(*fpaths).should == %w"bar/ bar/ cp/a cp/a".map{|s| File.join(Dir.pwd, s)}
|
90
|
+
app.assets_opts.values_at(*rpaths).should == %w"as/ as/ as/a as/a"
|
80
91
|
|
81
92
|
app.plugin :assets, :path=>'', :compiled_path=>nil
|
82
|
-
app.assets_opts.values_at(*
|
93
|
+
app.assets_opts.values_at(*fpaths).should == ['', '', 'a', 'a'].map{|s| File.join(Dir.pwd, s)}
|
94
|
+
app.assets_opts.values_at(*rpaths).should == ['as/', 'as/', 'as/a', 'as/a']
|
83
95
|
|
84
96
|
app.plugin :assets, :prefix=>''
|
85
|
-
app.assets_opts.values_at(*
|
97
|
+
app.assets_opts.values_at(*fpaths).should == ['', '', 'a', 'a'].map{|s| File.join(Dir.pwd, s)}
|
98
|
+
app.assets_opts.values_at(*rpaths).should == ['', '', 'a', 'a']
|
86
99
|
|
87
100
|
app.plugin :assets, :compiled_name=>nil
|
88
|
-
app.assets_opts.values_at(*
|
101
|
+
app.assets_opts.values_at(*fpaths).should == ['', ''].map{|s| File.join(Dir.pwd, s)} + ['', ''].map{|s| File.join(Dir.pwd, s).chop}
|
102
|
+
app.assets_opts.values_at(*rpaths).should == ['', '', '', '']
|
89
103
|
end
|
90
104
|
|
91
105
|
it 'assets_opts should use headers and dependencies given options' do
|
@@ -126,6 +140,22 @@ if run_tests
|
|
126
140
|
js.should include('console.log')
|
127
141
|
end
|
128
142
|
|
143
|
+
it 'should handle rendering assets, linking to them, and accepting requests for them when :add_script_name app option is used' do
|
144
|
+
app.opts[:add_script_name] = true
|
145
|
+
app.plugin :assets
|
146
|
+
html = body('/test', 'SCRIPT_NAME'=>'/foo')
|
147
|
+
html.scan(/<link/).length.should == 2
|
148
|
+
html =~ %r{href="/foo(/assets/css/app\.scss)"}
|
149
|
+
css = body($1)
|
150
|
+
html =~ %r{href="/foo(/assets/css/raw\.css)"}
|
151
|
+
css2 = body($1)
|
152
|
+
html.scan(/<script/).length.should == 1
|
153
|
+
html =~ %r{src="/foo(/assets/js/head/app\.js)"}
|
154
|
+
js = body($1)
|
155
|
+
css.should =~ /color: red;/
|
156
|
+
css2.should =~ /color: blue;/
|
157
|
+
end
|
158
|
+
|
129
159
|
it 'should handle rendering assets, linking to them, and accepting requests for them when not compiling, with different options' do
|
130
160
|
app.plugin :assets, :path=>'spec/', :js_dir=>'assets/js', :css_dir=>'assets/css', :prefix=>'a',
|
131
161
|
:js_route=>'foo', :css_route=>'bar', :add_suffix=>true, :css_opts=>{:style=>:compressed}
|
@@ -203,6 +233,21 @@ if run_tests
|
|
203
233
|
js.should include('console.log')
|
204
234
|
end
|
205
235
|
|
236
|
+
it 'should handle compiling assets, linking to them, and accepting requests for them when :add_script_name app option is used' do
|
237
|
+
app.opts[:add_script_name] = true
|
238
|
+
app.plugin :assets
|
239
|
+
app.compile_assets
|
240
|
+
html = body('/test', 'SCRIPT_NAME'=>'/foo')
|
241
|
+
html =~ %r{href="/foo(/assets/app\.[a-f0-9]{40}\.css)"}
|
242
|
+
css = body($1)
|
243
|
+
html.scan(/<script/).length.should == 1
|
244
|
+
html =~ %r{src="/foo(/assets/app\.head\.[a-f0-9]{40}\.js)"}
|
245
|
+
js = body($1)
|
246
|
+
css.should =~ /color: ?red/
|
247
|
+
css.should =~ /color: ?blue/
|
248
|
+
js.should include('console.log')
|
249
|
+
end
|
250
|
+
|
206
251
|
it 'should handle compiling assets, linking to them, and accepting requests for them, with different options' do
|
207
252
|
app.plugin :assets, :compiled_path=>nil, :js_dir=>'assets/js', :css_dir=>'assets/css', :prefix=>'a',
|
208
253
|
:public=>'spec/assets', :path=>'spec', :compiled_js_route=>'foo', :compiled_css_route=>'bar'
|
@@ -241,6 +286,29 @@ if run_tests
|
|
241
286
|
js.should include('console.log')
|
242
287
|
end
|
243
288
|
|
289
|
+
it 'should handle rendering assets, linking to them, and accepting requests for them when not compiling with a multi-level hash when :add_script_name app option is used' do
|
290
|
+
app.opts[:add_script_name] = true
|
291
|
+
app.plugin :assets, :path=>'spec', :js_dir=>nil, :css_dir=>nil, :compiled_js_dir=>nil, :compiled_css_dir=>nil,
|
292
|
+
:css=>{:assets=>{:css=>%w'app.scss raw.css'}}, :js=>{:assets=>{:js=>{:head=>'app.js'}}}
|
293
|
+
app.compile_assets
|
294
|
+
app.route do |r|
|
295
|
+
r.assets
|
296
|
+
r.is 'test' do
|
297
|
+
"#{assets([:css, :assets, :css])}\n#{assets([:js, :assets, :js, :head])}"
|
298
|
+
end
|
299
|
+
end
|
300
|
+
html = body('/test', 'SCRIPT_NAME'=>'/foo')
|
301
|
+
html.scan(/<link/).length.should == 1
|
302
|
+
html =~ %r{href="/foo(/assets/app\.assets\.css\.[a-f0-9]{40}\.css)"}
|
303
|
+
css = body($1)
|
304
|
+
html.scan(/<script/).length.should == 1
|
305
|
+
html =~ %r{src="/foo(/assets/app\.assets\.js\.head\.[a-f0-9]{40}\.js)"}
|
306
|
+
js = body($1)
|
307
|
+
css.should =~ /color: ?red/
|
308
|
+
css.should =~ /color: ?blue/
|
309
|
+
js.should include('console.log')
|
310
|
+
end
|
311
|
+
|
244
312
|
it 'should handle :group_subdirs => false when compiling' do
|
245
313
|
app.plugin :assets, :path=>'spec', :js_dir=>nil, :css_dir=>nil, :compiled_js_dir=>nil, :compiled_css_dir=>nil, :group_subdirs=>false,
|
246
314
|
:css=>{:assets=>{:css=>%w'assets/css/app.scss assets/css/raw.css'}}, :js=>{:assets=>{:js=>{:head=>'assets/js/head/app.js'}}}
|
@@ -410,4 +478,31 @@ if run_tests
|
|
410
478
|
app.allocate.assets([:js, :head]).should =~ %r{src="(/assets/app\.head\.[a-f0-9]{40}\.js)"}
|
411
479
|
end
|
412
480
|
end
|
481
|
+
|
482
|
+
describe 'assets plugin' do
|
483
|
+
it "app :root option affects :views default" do
|
484
|
+
app.plugin :assets
|
485
|
+
app.assets_opts[:path].should == File.join(Dir.pwd, 'assets')
|
486
|
+
app.assets_opts[:js_path].should == File.join(Dir.pwd, 'assets/js/')
|
487
|
+
app.assets_opts[:css_path].should == File.join(Dir.pwd, 'assets/css/')
|
488
|
+
|
489
|
+
app.opts[:root] = '/foo'
|
490
|
+
app.plugin :assets
|
491
|
+
app.assets_opts[:path].should == '/foo/assets'
|
492
|
+
app.assets_opts[:js_path].should == '/foo/assets/js/'
|
493
|
+
app.assets_opts[:css_path].should == '/foo/assets/css/'
|
494
|
+
|
495
|
+
app.opts[:root] = '/foo/bar'
|
496
|
+
app.plugin :assets
|
497
|
+
app.assets_opts[:path].should == '/foo/bar/assets'
|
498
|
+
app.assets_opts[:js_path].should == '/foo/bar/assets/js/'
|
499
|
+
app.assets_opts[:css_path].should == '/foo/bar/assets/css/'
|
500
|
+
|
501
|
+
app.opts[:root] = nil
|
502
|
+
app.plugin :assets
|
503
|
+
app.assets_opts[:path].should == File.join(Dir.pwd, 'assets')
|
504
|
+
app.assets_opts[:js_path].should == File.join(Dir.pwd, 'assets/js/')
|
505
|
+
app.assets_opts[:css_path].should == File.join(Dir.pwd, 'assets/css/')
|
506
|
+
end
|
507
|
+
end
|
413
508
|
end
|
@@ -12,4 +12,16 @@ describe "delete_empty_headers plugin" do
|
|
12
12
|
|
13
13
|
req[1].should == {'Bar'=>'1'}
|
14
14
|
end
|
15
|
+
|
16
|
+
it "is called when finishing with a body" do
|
17
|
+
app(:delete_empty_headers) do |r|
|
18
|
+
response['Foo'] = ''
|
19
|
+
response['Content-Type'] = ''
|
20
|
+
response['Content-Length'] = ''
|
21
|
+
response['Bar'] = '1'
|
22
|
+
r.halt response.finish_with_body(['a'])
|
23
|
+
end
|
24
|
+
|
25
|
+
req[1].should == {'Bar'=>'1'}
|
26
|
+
end
|
15
27
|
end
|
data/spec/plugin/mailer_spec.rb
CHANGED
@@ -87,6 +87,46 @@ describe "mailer plugin" do
|
|
87
87
|
m.attachments.length.should == 1
|
88
88
|
m.attachments.first.content_type.should =~ /mailer_spec\.rb/
|
89
89
|
m.content_type.should =~ /\Amultipart\/mixed/
|
90
|
+
m.parts.length.should == 1
|
91
|
+
m.parts.first.body.should == File.read(__FILE__)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "supports attachments with blocks" do
|
95
|
+
app(:mailer) do |r|
|
96
|
+
r.mail do
|
97
|
+
instance_exec(&setup_email)
|
98
|
+
add_file __FILE__ do
|
99
|
+
response.mail.attachments.last.content_type = 'text/foo'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
m = app.mail('foo')
|
105
|
+
m.attachments.length.should == 1
|
106
|
+
m.attachments.first.content_type.should == 'text/foo'
|
107
|
+
m.content_type.should =~ /\Amultipart\/mixed/
|
108
|
+
m.parts.length.should == 1
|
109
|
+
m.parts.first.body.should == File.read(__FILE__)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "supports plain-text attachments with an email body" do
|
113
|
+
app(:mailer) do |r|
|
114
|
+
r.mail do
|
115
|
+
instance_exec(&setup_email)
|
116
|
+
add_file :filename=>'a.txt', :content=>'b'
|
117
|
+
'c'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
m = app.mail('foo')
|
122
|
+
m.parts.length.should == 2
|
123
|
+
m.parts.first.content_type.should =~ /text\/plain/
|
124
|
+
m.parts.first.body.should == 'c'
|
125
|
+
m.parts.last.content_type.should =~ /text\/plain/
|
126
|
+
m.parts.last.body.should == 'b'
|
127
|
+
m.attachments.length.should == 1
|
128
|
+
m.attachments.first.content_type.should =~ /a\.txt/
|
129
|
+
m.content_type.should =~ /\Amultipart\/mixed/
|
90
130
|
end
|
91
131
|
|
92
132
|
it "supports regular web requests in same application" do
|
@@ -174,7 +214,7 @@ describe "mailer plugin" do
|
|
174
214
|
app.mail('/').content_type.should =~ /\Atext\/foo/
|
175
215
|
end
|
176
216
|
|
177
|
-
it "supports
|
217
|
+
it "supports setting the default content type when attachments are used" do
|
178
218
|
app(:bare) do
|
179
219
|
plugin :mailer, :content_type=>'text/html'
|
180
220
|
route do
|
@@ -184,8 +224,11 @@ describe "mailer plugin" do
|
|
184
224
|
end
|
185
225
|
m = app.mail('/')
|
186
226
|
m.content_type.should =~ /\Amultipart\/mixed/
|
187
|
-
m.parts.
|
188
|
-
m.parts.
|
227
|
+
m.parts.length.should == 2
|
228
|
+
m.parts.first.content_type.should =~ /\Atext\/html/
|
229
|
+
m.parts.first.body.should == "a"
|
230
|
+
m.parts.last.content_type.should =~ /\Atext\/css/
|
231
|
+
m.parts.last.body.should == File.read('spec/assets/css/raw.css')
|
189
232
|
end
|
190
233
|
end
|
191
234
|
end
|
@@ -28,4 +28,21 @@ describe "module_include plugin" do
|
|
28
28
|
|
29
29
|
req.should == [1, {}, []]
|
30
30
|
end
|
31
|
+
|
32
|
+
it "should work if called multiple times with a block" do
|
33
|
+
app(:bare) do
|
34
|
+
plugin :module_include
|
35
|
+
request_module{def h; halt response.f end}
|
36
|
+
request_module{def i; h end}
|
37
|
+
response_module{def f; finish end}
|
38
|
+
response_module{def finish; [1, {}, []] end}
|
39
|
+
|
40
|
+
route do |r|
|
41
|
+
r.i
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
req.should == [1, {}, []]
|
46
|
+
end
|
47
|
+
|
31
48
|
end
|
@@ -170,6 +170,16 @@ describe "multi_route plugin" do
|
|
170
170
|
end
|
171
171
|
end
|
172
172
|
|
173
|
+
describe "multi_route plugin" do
|
174
|
+
it "r.multi_route works even without routes defined" do
|
175
|
+
app(:multi_route) do |r|
|
176
|
+
r.multi_route
|
177
|
+
'a'
|
178
|
+
end
|
179
|
+
body.should == 'a'
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
173
183
|
describe "multi_route plugin" do
|
174
184
|
before do
|
175
185
|
app(:bare) do
|