roda 3.28.0 → 3.33.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (208) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +40 -0
  3. data/README.rdoc +15 -1
  4. data/doc/conventions.rdoc +17 -8
  5. data/doc/release_notes/3.29.0.txt +15 -0
  6. data/doc/release_notes/3.30.0.txt +14 -0
  7. data/doc/release_notes/3.31.0.txt +11 -0
  8. data/doc/release_notes/3.32.0.txt +42 -0
  9. data/doc/release_notes/3.33.0.txt +8 -0
  10. data/lib/roda.rb +3 -0
  11. data/lib/roda/plugins/_symbol_regexp_matchers.rb +2 -0
  12. data/lib/roda/plugins/assets.rb +26 -5
  13. data/lib/roda/plugins/caching.rb +2 -0
  14. data/lib/roda/plugins/common_logger.rb +1 -1
  15. data/lib/roda/plugins/content_security_policy.rb +2 -0
  16. data/lib/roda/plugins/default_headers.rb +2 -0
  17. data/lib/roda/plugins/exception_page.rb +9 -5
  18. data/lib/roda/plugins/hash_matcher.rb +1 -1
  19. data/lib/roda/plugins/header_matchers.rb +5 -1
  20. data/lib/roda/plugins/indifferent_params.rb +4 -0
  21. data/lib/roda/plugins/partials.rb +33 -6
  22. data/lib/roda/plugins/path.rb +42 -15
  23. data/lib/roda/plugins/placeholder_string_matchers.rb +2 -0
  24. data/lib/roda/plugins/public.rb +25 -17
  25. data/lib/roda/plugins/relative_path.rb +73 -0
  26. data/lib/roda/plugins/render.rb +17 -5
  27. data/lib/roda/plugins/render_each.rb +11 -3
  28. data/lib/roda/plugins/run_append_slash.rb +1 -1
  29. data/lib/roda/plugins/symbol_matchers.rb +2 -2
  30. data/lib/roda/version.rb +1 -1
  31. metadata +13 -214
  32. data/Rakefile +0 -108
  33. data/doc/release_notes/1.0.0.txt +0 -329
  34. data/doc/release_notes/1.1.0.txt +0 -226
  35. data/doc/release_notes/1.2.0.txt +0 -406
  36. data/doc/release_notes/1.3.0.txt +0 -109
  37. data/doc/release_notes/2.0.0.txt +0 -75
  38. data/doc/release_notes/2.1.0.txt +0 -124
  39. data/doc/release_notes/2.10.0.txt +0 -27
  40. data/doc/release_notes/2.11.0.txt +0 -70
  41. data/doc/release_notes/2.12.0.txt +0 -40
  42. data/doc/release_notes/2.13.0.txt +0 -10
  43. data/doc/release_notes/2.14.0.txt +0 -44
  44. data/doc/release_notes/2.15.0.txt +0 -53
  45. data/doc/release_notes/2.16.0.txt +0 -48
  46. data/doc/release_notes/2.17.0.txt +0 -62
  47. data/doc/release_notes/2.18.0.txt +0 -69
  48. data/doc/release_notes/2.19.0.txt +0 -30
  49. data/doc/release_notes/2.2.0.txt +0 -97
  50. data/doc/release_notes/2.20.0.txt +0 -5
  51. data/doc/release_notes/2.21.0.txt +0 -17
  52. data/doc/release_notes/2.22.0.txt +0 -41
  53. data/doc/release_notes/2.23.0.txt +0 -29
  54. data/doc/release_notes/2.24.0.txt +0 -65
  55. data/doc/release_notes/2.25.0.txt +0 -14
  56. data/doc/release_notes/2.26.0.txt +0 -13
  57. data/doc/release_notes/2.27.0.txt +0 -56
  58. data/doc/release_notes/2.28.0.txt +0 -17
  59. data/doc/release_notes/2.29.0.txt +0 -156
  60. data/doc/release_notes/2.3.0.txt +0 -109
  61. data/doc/release_notes/2.4.0.txt +0 -55
  62. data/doc/release_notes/2.5.0.txt +0 -23
  63. data/doc/release_notes/2.5.1.txt +0 -4
  64. data/doc/release_notes/2.6.0.txt +0 -21
  65. data/doc/release_notes/2.7.0.txt +0 -75
  66. data/doc/release_notes/2.8.0.txt +0 -44
  67. data/doc/release_notes/2.9.0.txt +0 -6
  68. data/spec/all.rb +0 -1
  69. data/spec/assets/css/app.scss +0 -1
  70. data/spec/assets/css/no_access.css +0 -1
  71. data/spec/assets/css/raw.css +0 -1
  72. data/spec/assets/js/head/app.js +0 -1
  73. data/spec/composition_spec.rb +0 -31
  74. data/spec/define_roda_method_spec.rb +0 -274
  75. data/spec/env_spec.rb +0 -11
  76. data/spec/freeze_spec.rb +0 -37
  77. data/spec/integration_spec.rb +0 -209
  78. data/spec/matchers_spec.rb +0 -832
  79. data/spec/opts_spec.rb +0 -42
  80. data/spec/plugin/_after_hook_spec.rb +0 -19
  81. data/spec/plugin/all_verbs_spec.rb +0 -29
  82. data/spec/plugin/assets_preloading_spec.rb +0 -98
  83. data/spec/plugin/assets_spec.rb +0 -745
  84. data/spec/plugin/backtracking_array_spec.rb +0 -42
  85. data/spec/plugin/branch_locals_spec.rb +0 -106
  86. data/spec/plugin/caching_spec.rb +0 -337
  87. data/spec/plugin/chunked_spec.rb +0 -201
  88. data/spec/plugin/class_level_routing_spec.rb +0 -164
  89. data/spec/plugin/class_matchers_spec.rb +0 -40
  90. data/spec/plugin/common_logger_spec.rb +0 -85
  91. data/spec/plugin/content_for_spec.rb +0 -162
  92. data/spec/plugin/content_security_policy_spec.rb +0 -175
  93. data/spec/plugin/cookies_spec.rb +0 -51
  94. data/spec/plugin/csrf_spec.rb +0 -111
  95. data/spec/plugin/default_headers_spec.rb +0 -82
  96. data/spec/plugin/default_status_spec.rb +0 -95
  97. data/spec/plugin/delay_build_spec.rb +0 -23
  98. data/spec/plugin/delegate_spec.rb +0 -23
  99. data/spec/plugin/delete_empty_headers_spec.rb +0 -27
  100. data/spec/plugin/direct_call_spec.rb +0 -28
  101. data/spec/plugin/disallow_file_uploads_spec.rb +0 -25
  102. data/spec/plugin/drop_body_spec.rb +0 -24
  103. data/spec/plugin/early_hints_spec.rb +0 -19
  104. data/spec/plugin/empty_root_spec.rb +0 -14
  105. data/spec/plugin/environments_spec.rb +0 -42
  106. data/spec/plugin/error_email_spec.rb +0 -97
  107. data/spec/plugin/error_handler_spec.rb +0 -216
  108. data/spec/plugin/error_mail_spec.rb +0 -93
  109. data/spec/plugin/exception_page_spec.rb +0 -168
  110. data/spec/plugin/flash_spec.rb +0 -121
  111. data/spec/plugin/h_spec.rb +0 -11
  112. data/spec/plugin/halt_spec.rb +0 -119
  113. data/spec/plugin/hash_matcher_spec.rb +0 -27
  114. data/spec/plugin/hash_routes_spec.rb +0 -535
  115. data/spec/plugin/head_spec.rb +0 -52
  116. data/spec/plugin/header_matchers_spec.rb +0 -98
  117. data/spec/plugin/heartbeat_spec.rb +0 -74
  118. data/spec/plugin/hooks_spec.rb +0 -152
  119. data/spec/plugin/indifferent_params_spec.rb +0 -14
  120. data/spec/plugin/json_parser_spec.rb +0 -141
  121. data/spec/plugin/json_spec.rb +0 -83
  122. data/spec/plugin/mail_processor_spec.rb +0 -451
  123. data/spec/plugin/mailer_spec.rb +0 -282
  124. data/spec/plugin/match_affix_spec.rb +0 -43
  125. data/spec/plugin/match_hook_spec.rb +0 -79
  126. data/spec/plugin/middleware_spec.rb +0 -237
  127. data/spec/plugin/middleware_stack_spec.rb +0 -81
  128. data/spec/plugin/module_include_spec.rb +0 -48
  129. data/spec/plugin/multi_route_spec.rb +0 -268
  130. data/spec/plugin/multi_run_spec.rb +0 -87
  131. data/spec/plugin/multi_view_spec.rb +0 -50
  132. data/spec/plugin/multibyte_string_matcher_spec.rb +0 -44
  133. data/spec/plugin/named_templates_spec.rb +0 -96
  134. data/spec/plugin/not_allowed_spec.rb +0 -69
  135. data/spec/plugin/not_found_spec.rb +0 -128
  136. data/spec/plugin/optimized_string_matchers_spec.rb +0 -43
  137. data/spec/plugin/padrino_render_spec.rb +0 -34
  138. data/spec/plugin/param_matchers_spec.rb +0 -69
  139. data/spec/plugin/params_capturing_spec.rb +0 -33
  140. data/spec/plugin/partials_spec.rb +0 -43
  141. data/spec/plugin/pass_spec.rb +0 -29
  142. data/spec/plugin/path_matchers_spec.rb +0 -42
  143. data/spec/plugin/path_rewriter_spec.rb +0 -45
  144. data/spec/plugin/path_spec.rb +0 -222
  145. data/spec/plugin/placeholder_string_matchers_spec.rb +0 -126
  146. data/spec/plugin/precompile_templates_spec.rb +0 -61
  147. data/spec/plugin/public_spec.rb +0 -85
  148. data/spec/plugin/render_each_spec.rb +0 -82
  149. data/spec/plugin/render_locals_spec.rb +0 -114
  150. data/spec/plugin/render_spec.rb +0 -912
  151. data/spec/plugin/request_aref_spec.rb +0 -51
  152. data/spec/plugin/request_headers_spec.rb +0 -39
  153. data/spec/plugin/response_request_spec.rb +0 -43
  154. data/spec/plugin/route_block_args_spec.rb +0 -86
  155. data/spec/plugin/route_csrf_spec.rb +0 -305
  156. data/spec/plugin/run_append_slash_spec.rb +0 -77
  157. data/spec/plugin/run_handler_spec.rb +0 -53
  158. data/spec/plugin/sessions_spec.rb +0 -452
  159. data/spec/plugin/shared_vars_spec.rb +0 -45
  160. data/spec/plugin/sinatra_helpers_spec.rb +0 -537
  161. data/spec/plugin/slash_path_empty_spec.rb +0 -22
  162. data/spec/plugin/static_routing_spec.rb +0 -192
  163. data/spec/plugin/static_spec.rb +0 -30
  164. data/spec/plugin/status_303_spec.rb +0 -28
  165. data/spec/plugin/status_handler_spec.rb +0 -158
  166. data/spec/plugin/streaming_spec.rb +0 -246
  167. data/spec/plugin/strip_path_prefix_spec.rb +0 -24
  168. data/spec/plugin/symbol_matchers_spec.rb +0 -51
  169. data/spec/plugin/symbol_status_spec.rb +0 -25
  170. data/spec/plugin/symbol_views_spec.rb +0 -32
  171. data/spec/plugin/timestamp_public_spec.rb +0 -85
  172. data/spec/plugin/type_routing_spec.rb +0 -348
  173. data/spec/plugin/typecast_params_spec.rb +0 -1370
  174. data/spec/plugin/unescape_path_spec.rb +0 -22
  175. data/spec/plugin/view_options_spec.rb +0 -170
  176. data/spec/plugin_spec.rb +0 -71
  177. data/spec/redirect_spec.rb +0 -41
  178. data/spec/request_spec.rb +0 -97
  179. data/spec/response_spec.rb +0 -199
  180. data/spec/route_spec.rb +0 -39
  181. data/spec/session_middleware_spec.rb +0 -129
  182. data/spec/session_spec.rb +0 -37
  183. data/spec/spec_helper.rb +0 -137
  184. data/spec/version_spec.rb +0 -14
  185. data/spec/views/_test.erb +0 -1
  186. data/spec/views/a.erb +0 -1
  187. data/spec/views/a.rdoc +0 -2
  188. data/spec/views/about.erb +0 -1
  189. data/spec/views/about.str +0 -1
  190. data/spec/views/about/_test.css.gz +0 -0
  191. data/spec/views/about/_test.erb +0 -1
  192. data/spec/views/about/_test.erb.gz +0 -0
  193. data/spec/views/about/comp_test.erb +0 -1
  194. data/spec/views/b.erb +0 -1
  195. data/spec/views/c.erb +0 -1
  196. data/spec/views/comp_layout.erb +0 -1
  197. data/spec/views/comp_test.erb +0 -1
  198. data/spec/views/content-yield.erb +0 -1
  199. data/spec/views/each.str +0 -1
  200. data/spec/views/home.erb +0 -2
  201. data/spec/views/home.str +0 -2
  202. data/spec/views/iv.erb +0 -1
  203. data/spec/views/layout-alternative.erb +0 -2
  204. data/spec/views/layout-yield.erb +0 -3
  205. data/spec/views/layout.erb +0 -2
  206. data/spec/views/layout.str +0 -2
  207. data/spec/views/multiple-layout.erb +0 -1
  208. data/spec/views/multiple.erb +0 -1
@@ -1,83 +0,0 @@
1
- require_relative "../spec_helper"
2
-
3
- describe "json plugin" do
4
- before do
5
- c = Class.new do
6
- def to_json
7
- '[1]'
8
- end
9
- end
10
-
11
- app(:bare) do
12
- plugin :json, :classes=>[Array, Hash, c]
13
-
14
- route do |r|
15
- r.is 'array' do
16
- [1, 2, 3]
17
- end
18
-
19
- r.is "hash" do
20
- {'a'=>'b'}
21
- end
22
-
23
- r.is 'c' do
24
- c.new
25
- end
26
-
27
- r.is 'd' do
28
- response['Content-Type'] = 'foo'
29
- c.new
30
- end
31
- end
32
- end
33
- end
34
-
35
- it "should use a json content type for a json response" do
36
- header('Content-Type', "/array").must_equal 'application/json'
37
- header('Content-Type', "/hash").must_equal 'application/json'
38
- header('Content-Type', "/c").must_equal 'application/json'
39
- header('Content-Type').must_equal 'text/html'
40
- end
41
-
42
- it "should not override existing content type for a json response" do
43
- header('Content-Type', "/d").must_equal 'foo'
44
- end
45
-
46
- it "should convert objects to json" do
47
- body('/array').gsub(/\s/, '').must_equal '[1,2,3]'
48
- body('/hash').gsub(/\s/, '').must_equal '{"a":"b"}'
49
- body('/c').must_equal '[1]'
50
- body.must_equal ''
51
- end
52
-
53
- it "should work when subclassing" do
54
- @app = Class.new(app)
55
- app.route{[1]}
56
- body.must_equal '[1]'
57
- end
58
-
59
- it "should accept custom serializers" do
60
- app.plugin :json, :serializer => proc{|o| o.inspect}
61
- body("/hash").must_equal '{"a"=>"b"}'
62
- end
63
-
64
- it "should give serializer the request if :include_request is set" do
65
- app.plugin :json,
66
- :include_request => true,
67
- :serializer => lambda{|o,r| "#{o['a']}:#{r.path_info}"}
68
-
69
- body("/hash").must_equal 'b:/hash'
70
- end
71
-
72
- it "should allow resetting :include_request to false" do
73
- app.plugin :json, :include_request => true
74
- app.plugin :json, :include_request => false
75
-
76
- body("/hash").must_equal '{"a":"b"}'
77
- end
78
-
79
- it "should allow custom content type for a response" do
80
- app.plugin :json, :content_type => "application/xml"
81
- header('Content-Type', "/array").must_equal 'application/xml'
82
- end
83
- end
@@ -1,451 +0,0 @@
1
- require_relative "../spec_helper"
2
-
3
- begin
4
- require 'mail'
5
- rescue LoadError
6
- warn "mail not installed, skipping mail_processor plugin test"
7
- else
8
- Mail.defaults do
9
- retriever_method :test
10
- end
11
-
12
- describe "mail_processor plugin" do
13
- def new_mail
14
- m = Mail.new(:to=>'a@example.com', :from=>'b@example.com', :cc=>'c@example.com', :bcc=>'d@example.com', :subject=>'Sub', :body=>'Bod')
15
- yield m if block_given?
16
- m
17
- end
18
-
19
- def check
20
- @processed.clear
21
- yield
22
- @processed
23
- end
24
-
25
- it "supports processing Mail instances via the routing tree using case insensitive address matchers" do
26
- @processed = processed = []
27
- app(:mail_processor) do |r|
28
- r.to('a@example.com') do
29
- r.handle_from(/@example.com/) do
30
- processed << :to_a1
31
- end
32
- r.handle_from(/\A(.+)@example(\d).com\z/i) do |pre, id|
33
- processed << :to_a2 << pre << id
34
- end
35
- r.handle_cc(['d@example.com', 'c@example.com']) do |ad|
36
- processed << :to_a3 << ad
37
- end
38
- r.handle do
39
- processed << :to_a4
40
- end
41
- end
42
- r.handle_to('e@example.com') do
43
- processed << :to_e
44
- end
45
- r.handle_rcpt('f@example.com') do
46
- processed << :to_f
47
- end
48
- end
49
-
50
- check{app.process_mail(new_mail)}.must_equal [:to_a1]
51
- check{app.process_mail(new_mail{|m| m.from 'b2@example2.com'})}.must_equal [:to_a2, "b2", "2"]
52
- check{app.process_mail(new_mail{|m| m.from 'b2@example12.com'})}.must_equal [:to_a3, 'c@example.com']
53
- check{app.process_mail(new_mail{|m| m.from 'b2@f.com'; m.cc []})}.must_equal [:to_a4]
54
- check{app.process_mail(new_mail{|m| m.to 'e@example.com'})}.must_equal [:to_e]
55
- check{app.process_mail(new_mail{|m| m.to 'f@example.com'})}.must_equal [:to_f]
56
- check{app.process_mail(new_mail{|m| m.to 'foo@example.com'; m.cc 'f@example.com'})}.must_equal [:to_f]
57
-
58
- app.freeze
59
-
60
- check{app.process_mail(new_mail{|m| m.to 'A@example.com'})}.must_equal [:to_a1]
61
- check{app.process_mail(new_mail{|m| m.from 'b2@Example2.com'})}.must_equal [:to_a2, "b2", "2"]
62
- check{app.process_mail(new_mail{|m| m.from 'b2@EXAMPLE12.com'})}.must_equal [:to_a3, 'c@example.com']
63
- check{app.process_mail(new_mail{|m| m.from 'b2@f.COM'; m.cc []})}.must_equal [:to_a4]
64
- check{app.process_mail(new_mail{|m| m.to 'E@EXAmple.com'})}.must_equal [:to_e]
65
- check{app.process_mail(new_mail{|m| m.to 'f@exAMPLe.com'})}.must_equal [:to_f]
66
- check{app.process_mail(new_mail{|m| m.to 'FOo@eXAMPle.com'; m.cc 'f@eXAMPle.com'})}.must_equal [:to_f]
67
- end
68
-
69
- it "supports processing Mail instances via the routing tree using body and subject matchers" do
70
- @processed = processed = []
71
- app(:mail_processor) do |r|
72
- r.handle_subject('Sub') do
73
- r.handle_body(/XID: (\d+)/) do |xid|
74
- processed << :sb << xid
75
- end
76
- processed << :s1
77
- end
78
- r.handle_subject(['Su', 'Si']) do |sub|
79
- processed << :s2 << sub
80
- end
81
- r.subject(/S([ao])/) do |sub|
82
- r.handle do
83
- processed << :s3 << sub
84
- end
85
- end
86
- end
87
-
88
- check{app.process_mail(new_mail)}.must_equal [:s1]
89
- check{app.process_mail(new_mail{|m| m.subject 'Si'})}.must_equal [:s2, 'Si']
90
- check{app.process_mail(new_mail{|m| m.subject 'Sa'})}.must_equal [:s3, 'a']
91
- check{app.process_mail(new_mail{|m| m.body 'XID: 1234'})}.must_equal [:sb, '1234']
92
- end
93
-
94
- it "supports processing Mail instances via the routing tree using header matchers" do
95
- @processed = processed = []
96
- app(:mail_processor) do |r|
97
- r.handle_header('X-Test') do |v|
98
- processed << :x1 << v
99
- end
100
- r.handle_header('X-Test2', 'Foo') do
101
- processed << :x2
102
- end
103
- r.handle_header('X-Test2', ['Foo', 'Bar']) do |val|
104
- processed << :x3 << val
105
- end
106
- r.header('X-Test2', /(\d+)/) do |i|
107
- r.handle do
108
- processed << :x4 << i
109
- end
110
- end
111
- r.handle do
112
- processed << :f
113
- end
114
- end
115
-
116
- check{app.process_mail(new_mail)}.must_equal [:f]
117
- check{app.process_mail(new_mail{|m| m.header['X-Test'] = 'Foo'})}.must_equal [:x1, 'Foo']
118
- check{app.process_mail(new_mail{|m| m.header['X-Test2'] = 'Foo'})}.must_equal [:x2]
119
- check{app.process_mail(new_mail{|m| m.header['X-Test2'] = 'Bar'})}.must_equal [:x3, 'Bar']
120
- check{app.process_mail(new_mail{|m| m.header['X-Test2'] = 'foo 3'})}.must_equal [:x4, '3']
121
- end
122
-
123
- it "calls unhandled_mail block for email not handled by a routing block" do
124
- @processed = processed = []
125
- app(:mail_processor) do |r|
126
- r.to('a@example.com') do
127
- processed << :on_to
128
- end
129
- processed << :miss
130
- end
131
- app.unhandled_mail do
132
- processed << :uh << mail.to.first
133
- end
134
- check{app.process_mail(new_mail)}.must_equal [:on_to, :uh, 'a@example.com']
135
- check{app.process_mail(new_mail{|m| m.to 'b@example.com'})}.must_equal [:miss, :uh, 'b@example.com']
136
- end
137
-
138
- it "calls handled_mail block for email handled by a routing block" do
139
- @processed = processed = []
140
- app(:mail_processor) do |r|
141
- r.handle_to('a@example.com') do
142
- processed << :to
143
- end
144
- end
145
- app.handled_mail do
146
- processed << :h << mail.to.first
147
- end
148
- check{app.process_mail(new_mail)}.must_equal [:to, :h, 'a@example.com']
149
- end
150
-
151
- it "raises by default for unhandled email" do
152
- @processed = processed = []
153
- app(:mail_processor) do |r|
154
- processed << :miss
155
- end
156
- proc{app.process_mail(new_mail)}.must_raise Roda::RodaPlugins::MailProcessor::UnhandledMail
157
- processed.must_equal [:miss]
158
- end
159
-
160
- it "allows calling unhandled_mail directly, and not calling either implicitly if called directly" do
161
- @processed = processed = []
162
- app(:mail_processor) do |r|
163
- r.handle_to('a@example.com') do
164
- r.handle_from('b@example.com') do
165
- processed << :quux
166
- end
167
- unhandled_mail "bar"
168
- processed << :foo
169
- end
170
- r.to('d@example.com') do
171
- r.handle do
172
- processed << :bar
173
- unhandled_mail "foo"
174
- end
175
- end
176
- r.handle do
177
- processed << :baz
178
- end
179
- end
180
- app.unhandled_mail do
181
- processed << :uh
182
- end
183
- app.handled_mail do
184
- processed << :h
185
- end
186
- app.after_mail do
187
- processed << :a
188
- end
189
- check{app.process_mail(new_mail)}.must_equal [:quux, :h, :a]
190
- check{app.process_mail(new_mail{|m| m.from 'c@example.com'})}.must_equal [:uh, :a]
191
- check{app.process_mail(new_mail{|m| m.to 'd@example.com'})}.must_equal [ :bar, :uh, :a]
192
- check{app.process_mail(new_mail{|m| m.to 'e@example.com'})}.must_equal [ :baz, :h, :a]
193
- end
194
-
195
- it "always calls after_mail after processing an email, even if the mail is not handled" do
196
- @processed = processed = []
197
- app(:mail_processor) do |r|
198
- r.handle_to('a@example.com') do
199
- processed << :t
200
- end
201
- r.handle_to('b@example.com') do
202
- raise
203
- end
204
- end
205
- app.unhandled_mail do
206
- processed << :uh
207
- end
208
- app.after_mail do
209
- processed << :a
210
- end
211
- check{app.process_mail(new_mail)}.must_equal [:t, :a]
212
- check{app.process_mail(new_mail{|m| m.to 'd@example.com'})}.must_equal [:uh, :a]
213
- check{proc{app.process_mail(new_mail{|m| m.to 'b@example.com'})}.must_raise RuntimeError}.must_equal [:a]
214
- end
215
-
216
- it "always calls after_mail after processing an email, even if handled_mail or unhandled_mail hooks raise an exception" do
217
- @processed = processed = []
218
- app(:mail_processor) do |r|
219
- r.handle_to('a@example.com') do
220
- processed << :t
221
- end
222
- end
223
- app.handled_mail do
224
- processed << :h
225
- raise "foo"
226
- end
227
- app.unhandled_mail do
228
- processed << :uh
229
- raise "foo"
230
- end
231
- app.after_mail do
232
- processed << :a
233
- end
234
- check{proc{app.process_mail(new_mail)}.must_raise RuntimeError}.must_equal [:t, :h, :a]
235
- check{proc{app.process_mail(new_mail{|m| m.to 'd@example.com'})}.must_raise RuntimeError}.must_equal [:uh, :a]
236
- end
237
-
238
- it "should raise RodaError for unsupported address and content matchers" do
239
- app(:mail_processor) do |r|
240
- r.subject('Sub') do
241
- r.subject(Object.new) do
242
- end
243
- end
244
- r.subject('Si') do
245
- r.from(Object.new) do
246
- end
247
- end
248
- end
249
-
250
- proc{app.process_mail(new_mail)}.must_raise Roda::RodaError
251
- proc{app.process_mail(new_mail{|m| m.subject 'Si'})}.must_raise Roda::RodaError
252
- end
253
-
254
- it "supports processing retrieved mail from a mailbox via the routing tree" do
255
- @processed = processed = []
256
- app(:mail_processor) do |r|
257
- r.handle_to('a@example.com') do
258
- processed << :to_a
259
- end
260
- r.handle_to('c@example.com') do
261
- processed.concat(mail.to)
262
- end
263
- end
264
- Mail::TestRetriever.emails = [new_mail]
265
- check{app.process_mailbox}.must_equal [:to_a]
266
- Mail::TestRetriever.emails = [new_mail{|m| m.to 'c@example.com'}]
267
- check{app.process_mailbox}.must_equal ['c@example.com']
268
- Mail::TestRetriever.emails = [new_mail] * 10
269
- check{app.process_mailbox}.must_equal([:to_a]*10)
270
- Mail::TestRetriever.emails = Array.new(10){new_mail}
271
- check{app.process_mailbox(:count=>2)}.must_equal([:to_a]*2)
272
- check{app.process_mailbox}.must_equal([:to_a]*8)
273
- end
274
-
275
- it "supports processing retrieved mail from a mailbox with a custom :retreiver" do
276
- @processed = processed = []
277
- emails = []
278
- retriever = Class.new(Mail::Retriever) do
279
- define_method(:find) do |opts={}, &block|
280
- es = emails.dup
281
- emails.clear
282
- es.each(&block) if block
283
- es
284
- end
285
- end.new
286
- app(:mail_processor) do |r|
287
- r.handle_to('a@example.com') do
288
- processed << :to_a
289
- end
290
- end
291
- emails << new_mail
292
- check{app.process_mailbox}.must_equal []
293
- emails.wont_be_empty
294
- check{app.process_mailbox(:retriever=>retriever)}.must_equal [:to_a]
295
- emails.must_be_empty
296
- check{app.process_mailbox(:retriever=>retriever)}.must_equal []
297
- end
298
-
299
- it "supports rcpt class method to delegate to blocks by recipient address, falling back to main routing block" do
300
- @processed = processed = []
301
- app(:mail_processor) do |r|
302
- r.handle do
303
- processed << :f
304
- end
305
- end
306
- app.rcpt('a@example.com') do |r|
307
- r.handle do
308
- processed << :a
309
- end
310
- end
311
- app.rcpt(/(.*[bcd])@example.com/i) do |r, x|
312
- r.handle do
313
- processed << :bcd << x
314
- end
315
- end
316
- app.rcpt(/([cde])@example.com(.*)/i) do |r, x, y|
317
- r.handle do
318
- processed << :cde << x << y
319
- end
320
- end
321
- app.rcpt('B@EXAMPLE.com', 'c@example.com') do |r|
322
- r.handle do
323
- processed << :bc
324
- end
325
- end
326
- app.rcpt('x@example.com') do |r|
327
- processed << :x
328
- end
329
- proc{app.rcpt(Object.new){}}.must_raise Roda::RodaError
330
-
331
- check{app.process_mail(new_mail)}.must_equal [:a]
332
-
333
- app.freeze
334
-
335
- check{app.process_mail(new_mail{|m| m.to 'b@example.com'})}.must_equal [:bc]
336
- check{app.process_mail(new_mail{|m| m.to 'C@example.com'; m.cc 'a@example.com'})}.must_equal [:bc]
337
- check{app.process_mail(new_mail{|m| m.to 'd@example.com'; m.cc 'a@example.com'})}.must_equal [:a]
338
- check{app.process_mail(new_mail{|m| m.to 'd@example.com'; m.cc []})}.must_equal [:bcd, 'd']
339
- check{app.process_mail(new_mail{|m| m.to '123d@example.com123'; m.cc []})}.must_equal [:bcd, '123d']
340
- check{app.process_mail(new_mail{|m| m.to 'e@example.com'; m.cc []})}.must_equal [:cde, 'e', '']
341
- check{app.process_mail(new_mail{|m| m.to '123e@example.com123'; m.cc []})}.must_equal [:cde, 'e', '123']
342
- check{proc{app.process_mail(new_mail{|m| m.to 'x@example.com'})}.must_raise Roda::RodaPlugins::MailProcessor::UnhandledMail}.must_equal [:x]
343
- end
344
-
345
- it "supports mail_recipients class method to set recipients of mail, respected by rcpt methods" do
346
- @processed = processed = []
347
- app(:mail_processor) do |r|
348
- r.handle_rcpt('a@example.com') do
349
- processed << :a
350
- end
351
- r.handle do
352
- processed << :f
353
- end
354
- end
355
- app.rcpt('b@example.com') do |r|
356
- r.handle do
357
- processed << :b
358
- end
359
- end
360
- check{app.process_mail(new_mail)}.must_equal [:a]
361
- check{app.process_mail(new_mail{|m| m.to 'b@example.com'})}.must_equal [:b]
362
- check{app.process_mail(new_mail{|m| m.to 'e@example.com'})}.must_equal [:f]
363
-
364
- app.mail_recipients do
365
- if smtp_rcpt = header['X-SMTP-To']
366
- smtp_rcpt = smtp_rcpt.decoded
367
- end
368
- Array(smtp_rcpt)
369
- end
370
- check{app.process_mail(new_mail)}.must_equal [:f]
371
- check{app.process_mail(new_mail{|m| m.header['X-SMTP-To'] = 'a@example.com'})}.must_equal [:a]
372
- check{app.process_mail(new_mail{|m| m.header['X-SMTP-To'] = 'b@example.com'})}.must_equal [:b]
373
- end
374
-
375
- it "supports #mail_text, .mail_text, and r.text for allowing the ability to extract text from mails" do
376
- @processed = processed = []
377
- app(:mail_processor) do |r|
378
- r.handle_text(/Found (foo|bar)/) do |x|
379
- processed << :f << x
380
- end
381
- r.text(/Found (baz|quux)/) do |x|
382
- r.handle do
383
- processed << :f2 << x << mail_text
384
- end
385
- end
386
- r.handle do
387
- processed << :nf << mail_text
388
- end
389
- end
390
- check{app.process_mail(new_mail)}.must_equal [:nf, 'Bod']
391
- check{app.process_mail(new_mail{|m| m.body "Found bar\n--\nFound foo"})}.must_equal [:f, 'bar']
392
- check{app.process_mail(new_mail{|m| m.body "> Found baz\nFound quux"})}.must_equal [:f2, 'baz', "> Found baz\nFound quux"]
393
- @app.mail_text do
394
- text = mail.body.decoded.gsub(/^>[^\r\n]*\r?\n/m, '')
395
- text.split(/\r?\n--\r?\n/).last
396
- end
397
- check{app.process_mail(new_mail)}.must_equal [:nf, 'Bod']
398
- check{app.process_mail(new_mail{|m| m.body "Found bar\n--\nFound foo"})}.must_equal [:f, 'foo']
399
- check{app.process_mail(new_mail{|m| m.body "> Found baz\nFound quux"})}.must_equal [:f2, 'quux', "Found quux"]
400
- end
401
-
402
- it "works with route_block_args plugin" do
403
- @processed = processed = []
404
- app(:bare) do
405
- plugin :mail_processor
406
- plugin :route_block_args do
407
- [to, from]
408
- end
409
- route do |t, f|
410
- request.handle do
411
- processed << t << f
412
- end
413
- end
414
- handled_mail do
415
- # processed << :h << mail.to.first
416
- end
417
- end
418
- check{app.process_mail(new_mail)}.must_equal [["a@example.com"], ["b@example.com"]]
419
- end
420
-
421
- it "works with hooks plugin, calling after hook before *_mail hooks" do
422
- @processed = processed = []
423
- app(:bare) do
424
- plugin :mail_processor
425
- plugin :hooks
426
- before do
427
- processed << 1
428
- end
429
- after do
430
- processed << 2
431
- end
432
- route do |r|
433
- processed << 3
434
- r.handle_to('a@example.com') do
435
- end
436
- end
437
- handled_mail do
438
- processed << 4
439
- end
440
- unhandled_mail do
441
- processed << 5
442
- end
443
- after_mail do
444
- processed << 6
445
- end
446
- end
447
- check{app.process_mail(new_mail)}.must_equal [1, 3, 2, 4, 6]
448
- check{app.process_mail(new_mail{|m| m.to 'x@example.com'})}.must_equal [1, 3, 2, 5, 6]
449
- end
450
- end
451
- end