tennpipes-base 3.6.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.rdoc +294 -0
  4. data/Rakefile +1 -0
  5. data/bin/tennpipes +8 -0
  6. data/lib/tennpipes-base.rb +196 -0
  7. data/lib/tennpipes-base/application.rb +175 -0
  8. data/lib/tennpipes-base/application/application_setup.rb +202 -0
  9. data/lib/tennpipes-base/application/authenticity_token.rb +25 -0
  10. data/lib/tennpipes-base/application/flash.rb +229 -0
  11. data/lib/tennpipes-base/application/params_protection.rb +129 -0
  12. data/lib/tennpipes-base/application/routing.rb +1002 -0
  13. data/lib/tennpipes-base/application/show_exceptions.rb +50 -0
  14. data/lib/tennpipes-base/caller.rb +53 -0
  15. data/lib/tennpipes-base/cli/adapter.rb +33 -0
  16. data/lib/tennpipes-base/cli/base.rb +105 -0
  17. data/lib/tennpipes-base/cli/console.rb +20 -0
  18. data/lib/tennpipes-base/cli/launcher.rb +103 -0
  19. data/lib/tennpipes-base/cli/rake.rb +50 -0
  20. data/lib/tennpipes-base/cli/rake_tasks.rb +72 -0
  21. data/lib/tennpipes-base/command.rb +38 -0
  22. data/lib/tennpipes-base/ext/sinatra.rb +29 -0
  23. data/lib/tennpipes-base/filter.rb +52 -0
  24. data/lib/tennpipes-base/images/404.png +0 -0
  25. data/lib/tennpipes-base/images/500.png +0 -0
  26. data/lib/tennpipes-base/loader.rb +202 -0
  27. data/lib/tennpipes-base/logger.rb +492 -0
  28. data/lib/tennpipes-base/module.rb +58 -0
  29. data/lib/tennpipes-base/mounter.rb +308 -0
  30. data/lib/tennpipes-base/path_router.rb +119 -0
  31. data/lib/tennpipes-base/path_router/compiler.rb +110 -0
  32. data/lib/tennpipes-base/path_router/error_handler.rb +8 -0
  33. data/lib/tennpipes-base/path_router/matcher.rb +123 -0
  34. data/lib/tennpipes-base/path_router/route.rb +169 -0
  35. data/lib/tennpipes-base/reloader.rb +309 -0
  36. data/lib/tennpipes-base/reloader/rack.rb +26 -0
  37. data/lib/tennpipes-base/reloader/storage.rb +55 -0
  38. data/lib/tennpipes-base/router.rb +98 -0
  39. data/lib/tennpipes-base/server.rb +119 -0
  40. data/lib/tennpipes-base/tasks.rb +21 -0
  41. data/lib/tennpipes-base/version.rb +20 -0
  42. data/lib/tennpipes-base/version.rb~ +20 -0
  43. data/test/fixtures/app_gem/Gemfile +4 -0
  44. data/test/fixtures/app_gem/app/app.rb +3 -0
  45. data/test/fixtures/app_gem/app_gem.gemspec +17 -0
  46. data/test/fixtures/app_gem/lib/app_gem.rb +7 -0
  47. data/test/fixtures/app_gem/lib/app_gem/version.rb +3 -0
  48. data/test/fixtures/apps/complex.rb +32 -0
  49. data/test/fixtures/apps/demo_app.rb +7 -0
  50. data/test/fixtures/apps/demo_demo.rb +7 -0
  51. data/test/fixtures/apps/demo_project/api/app.rb +7 -0
  52. data/test/fixtures/apps/demo_project/api/lib/api_lib.rb +3 -0
  53. data/test/fixtures/apps/demo_project/app.rb +7 -0
  54. data/test/fixtures/apps/external_apps/fake_lib.rb +1 -0
  55. data/test/fixtures/apps/external_apps/fake_root.rb +2 -0
  56. data/test/fixtures/apps/helpers/class_methods_helpers.rb +4 -0
  57. data/test/fixtures/apps/helpers/instance_methods_helpers.rb +4 -0
  58. data/test/fixtures/apps/helpers/support.rb +1 -0
  59. data/test/fixtures/apps/helpers/system_helpers.rb +8 -0
  60. data/test/fixtures/apps/kiq.rb +3 -0
  61. data/test/fixtures/apps/lib/myklass.rb +2 -0
  62. data/test/fixtures/apps/lib/myklass/mysubklass.rb +4 -0
  63. data/test/fixtures/apps/models/child.rb +2 -0
  64. data/test/fixtures/apps/models/parent.rb +5 -0
  65. data/test/fixtures/apps/mountable_apps/rack_apps.rb +15 -0
  66. data/test/fixtures/apps/mountable_apps/static.html +1 -0
  67. data/test/fixtures/apps/precompiled_app.rb +19 -0
  68. data/test/fixtures/apps/simple.rb +32 -0
  69. data/test/fixtures/apps/static.rb +10 -0
  70. data/test/fixtures/apps/system.rb +13 -0
  71. data/test/fixtures/apps/system_class_methods_demo.rb +7 -0
  72. data/test/fixtures/apps/system_instance_methods_demo.rb +7 -0
  73. data/test/fixtures/dependencies/a.rb +9 -0
  74. data/test/fixtures/dependencies/b.rb +4 -0
  75. data/test/fixtures/dependencies/c.rb +1 -0
  76. data/test/fixtures/dependencies/circular/e.rb +13 -0
  77. data/test/fixtures/dependencies/circular/f.rb +2 -0
  78. data/test/fixtures/dependencies/circular/g.rb +2 -0
  79. data/test/fixtures/dependencies/d.rb +4 -0
  80. data/test/fixtures/reloadable_apps/external/app/app.rb +6 -0
  81. data/test/fixtures/reloadable_apps/external/app/controllers/base.rb +6 -0
  82. data/test/fixtures/reloadable_apps/main/app.rb +10 -0
  83. data/test/helper.rb +30 -0
  84. data/test/test_application.rb +185 -0
  85. data/test/test_core.rb +93 -0
  86. data/test/test_csrf_protection.rb +208 -0
  87. data/test/test_dependencies.rb +57 -0
  88. data/test/test_filters.rb +389 -0
  89. data/test/test_flash.rb +168 -0
  90. data/test/test_locale.rb +21 -0
  91. data/test/test_logger.rb +295 -0
  92. data/test/test_mounter.rb +302 -0
  93. data/test/test_params_protection.rb +195 -0
  94. data/test/test_reloader_complex.rb +74 -0
  95. data/test/test_reloader_external.rb +21 -0
  96. data/test/test_reloader_simple.rb +101 -0
  97. data/test/test_reloader_system.rb +113 -0
  98. data/test/test_restful_routing.rb +33 -0
  99. data/test/test_router.rb +281 -0
  100. data/test/test_routing.rb +2328 -0
  101. metadata +301 -0
@@ -0,0 +1,93 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+
3
+ describe "Core" do
4
+ def setup
5
+ Tennpipes.clear!
6
+ end
7
+
8
+ describe 'for core functionality' do
9
+ it 'should check some global methods' do
10
+ assert_respond_to Tennpipes, :root
11
+ assert_respond_to Tennpipes, :env
12
+ assert_respond_to Tennpipes, :application
13
+ assert_respond_to Tennpipes, :set_encoding
14
+ assert_respond_to Tennpipes, :load!
15
+ assert_respond_to Tennpipes, :reload!
16
+ assert_respond_to Tennpipes, :version
17
+ assert_respond_to Tennpipes, :configure_apps
18
+ end
19
+
20
+ it 'should validate global helpers' do
21
+ assert_equal :test, Tennpipes.env
22
+ assert_match /\/test/, Tennpipes.root
23
+ refute_nil Tennpipes.version
24
+ end
25
+
26
+ it 'should set correct utf-8 encoding' do
27
+ Tennpipes.set_encoding
28
+ assert_equal Encoding.default_external, Encoding::UTF_8
29
+ assert_equal Encoding.default_internal, Encoding::UTF_8
30
+ end
31
+
32
+ it 'should raise application error if I instantiate a new tennpipes application without mounted apps' do
33
+ text = capture_io { Tennpipes.application }
34
+ assert_match /No apps are mounted/, text.to_s
35
+ end
36
+
37
+ it 'should check before/after tennpipes load hooks' do
38
+ Tennpipes.before_load { @_foo = 1 }
39
+ Tennpipes.after_load { @_foo += 1 }
40
+ Tennpipes.load!
41
+ assert_equal 1, Tennpipes.before_load.size
42
+ assert_equal 1, Tennpipes.after_load.size
43
+ assert_equal 2, @_foo
44
+ end
45
+
46
+ it 'should add middlewares in front if specified' do
47
+ test = Class.new {
48
+ def initialize(app)
49
+ @app = app
50
+ end
51
+
52
+ def call(env)
53
+ status, headers, body = @app.call(env)
54
+ headers["Middleware-Called"] = "yes"
55
+ return status, headers, body
56
+ end
57
+ }
58
+
59
+ class Foo < Tennpipes::Application; end
60
+
61
+ Tennpipes.use(test)
62
+ Tennpipes.mount(Foo).to("/")
63
+
64
+ res = Rack::MockRequest.new(Tennpipes.application).get("/")
65
+ assert_equal "yes", res["Middleware-Called"]
66
+ end
67
+
68
+ it 'should properly set default options' do
69
+ mock_app do
70
+ default :foo, :bar
71
+ default :zoo, :baz
72
+ set :foo, :bam
73
+ set :moo, :bam
74
+ default :moo, :ban
75
+ end
76
+ assert_equal @app.settings.foo, :bam
77
+ assert_equal @app.settings.zoo, :baz
78
+ assert_equal @app.settings.moo, :bam
79
+ end
80
+
81
+ it 'should return a friendly 500' do
82
+ mock_app do
83
+ enable :show_exceptions
84
+ get(:index){ raise StandardError }
85
+ end
86
+
87
+ get "/"
88
+ assert_equal 500, status
89
+ assert body.include?("StandardError")
90
+ assert body.include?("<code>show_exceptions</code> setting")
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,208 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+
3
+ describe "Application" do
4
+ before { Tennpipes.clear! }
5
+
6
+ describe 'CSRF protection' do
7
+ describe "with CSRF protection on" do
8
+ before do
9
+ mock_app do
10
+ enable :sessions
11
+ enable :protect_from_csrf
12
+ post('/'){ 'HI' }
13
+ end
14
+ end
15
+
16
+ it 'should not allow requests without tokens' do
17
+ post "/"
18
+ assert_equal 403, status
19
+ end
20
+
21
+ it 'should allow requests with correct tokens' do
22
+ post "/", {"authenticity_token" => "a"}, 'rack.session' => {:csrf => "a"}
23
+ assert_equal 200, status
24
+ end
25
+
26
+ it 'should not allow requests with incorrect tokens' do
27
+ post "/", {"authenticity_token" => "a"}, 'rack.session' => {:csrf => "b"}
28
+ assert_equal 403, status
29
+ end
30
+
31
+ it 'should allow requests with correct X-CSRF-TOKEN' do
32
+ post "/", {}, 'rack.session' => {:csrf => "a"}, 'HTTP_X_CSRF_TOKEN' => "a"
33
+ assert_equal 200, status
34
+ end
35
+
36
+ it 'should not allow requests with incorrect X-CSRF-TOKEN' do
37
+ post "/", {}, 'rack.session' => {:csrf => "a"}, 'HTTP_X_CSRF_TOKEN' => "b"
38
+ assert_equal 403, status
39
+ end
40
+
41
+ end
42
+
43
+ describe "without CSRF protection on" do
44
+ before do
45
+ mock_app do
46
+ enable :sessions
47
+ disable :protect_from_csrf
48
+ post('/'){ 'HI' }
49
+ end
50
+ end
51
+
52
+ it 'should allows requests without tokens' do
53
+ post "/"
54
+ assert_equal 200, status
55
+ end
56
+
57
+ it 'should allow requests with correct tokens' do
58
+ post "/", {"authenticity_token" => "a"}, 'rack.session' => {:csrf => "a"}
59
+ assert_equal 200, status
60
+ end
61
+
62
+ it 'should allow requests with incorrect tokens' do
63
+ post "/", {"authenticity_token" => "a"}, 'rack.session' => {:csrf => "b"}
64
+ assert_equal 200, status
65
+ end
66
+
67
+ it 'should allow requests with correct X-CSRF-TOKEN' do
68
+ post "/", {}, 'rack.session' => {:csrf => "a"}, 'HTTP_X_CSRF_TOKEN' => "a"
69
+ assert_equal 200, status
70
+ end
71
+
72
+ it 'should allow requests with incorrect X-CSRF-TOKEN' do
73
+ post "/", {}, 'rack.session' => {:csrf => "a"}, 'HTTP_X_CSRF_TOKEN' => "b"
74
+ assert_equal 200, status
75
+ end
76
+ end
77
+
78
+ describe "with optional CSRF protection" do
79
+ before do
80
+ mock_app do
81
+ enable :sessions
82
+ enable :protect_from_csrf
83
+ enable :allow_disabled_csrf
84
+ post('/on') { 'HI' }
85
+ post('/off', :csrf_protection => false) { 'HI' }
86
+ end
87
+ end
88
+
89
+ it 'should allow access to routes with csrf_protection off' do
90
+ post "/off"
91
+ assert_equal 200, status
92
+ end
93
+
94
+ it 'should not allow access to routes with csrf_protection on' do
95
+ post "/on"
96
+ assert_equal 403, status
97
+ assert_equal 'Forbidden', body
98
+ end
99
+ end
100
+
101
+ describe "with :except option that is using Proc" do
102
+ before do
103
+ mock_app do
104
+ enable :sessions
105
+ set :protect_from_csrf, :except => proc{|env| ["/", "/foo"].any?{|path| path == env['PATH_INFO'] }}
106
+ post("/") { "Hello" }
107
+ post("/foo") { "Hello, foo" }
108
+ post("/bar") { "Hello, bar" }
109
+ end
110
+ end
111
+
112
+ it 'should allow ignoring CSRF protection on specific routes' do
113
+ post "/"
114
+ assert_equal 200, status
115
+ post "/foo"
116
+ assert_equal 200, status
117
+ post "/bar"
118
+ assert_equal 403, status
119
+ end
120
+ end
121
+
122
+ describe "with :except option that is using String and Regexp" do
123
+ before do
124
+ mock_app do
125
+ enable :sessions
126
+ set :protect_from_csrf, :except => ["/a", %r{^/a.c$}]
127
+ post("/a") { "a" }
128
+ post("/abc") { "abc" }
129
+ post("/foo") { "foo" }
130
+ end
131
+ end
132
+
133
+ it 'should allow ignoring CSRF protection on specific routes' do
134
+ post "/a"
135
+ assert_equal 200, status
136
+ post "/abc"
137
+ assert_equal 200, status
138
+ post "/foo"
139
+ assert_equal 403, status
140
+ end
141
+ end
142
+
143
+ describe "with custom protection options" do
144
+ before do
145
+ mock_app do
146
+ enable :sessions
147
+ set :protect_from_csrf, :authenticity_param => 'foobar', :message => 'sucker!'
148
+ post("/a") { "a" }
149
+ end
150
+ end
151
+
152
+ it 'should allow configuring protection options' do
153
+ post "/a", {"foobar" => "a"}, 'rack.session' => {:csrf => "a"}
154
+ assert_equal 200, status
155
+ end
156
+
157
+ it 'should allow configuring message' do
158
+ post "/a"
159
+ assert_equal 403, status
160
+ assert_equal 'sucker!', body
161
+ end
162
+ end
163
+
164
+ describe "with middleware" do
165
+ before do
166
+ class Middleware < Sinatra::Base
167
+ post("/middleware") { "Hello, middleware" }
168
+ post("/dummy") { "Hello, dummy" }
169
+ end
170
+ mock_app do
171
+ enable :sessions
172
+ set :protect_from_csrf, :except => proc{|env| ["/", "/middleware"].any?{|path| path == env['PATH_INFO'] }}
173
+ use Middleware
174
+ post("/") { "Hello" }
175
+ end
176
+ end
177
+
178
+ it 'should allow ignoring CSRF protection on specific routes of middleware' do
179
+ post "/"
180
+ assert_equal 200, status
181
+ post "/middleware"
182
+ assert_equal 200, status
183
+ post "/dummy"
184
+ assert_equal 403, status
185
+ end
186
+ end
187
+
188
+ describe "with standard report layout" do
189
+ before do
190
+ mock_app do
191
+ enable :sessions
192
+ set :protect_from_csrf, :message => 'sucker!'
193
+ enable :report_csrf_failure
194
+ post("/a") { "a" }
195
+ error 403 do
196
+ halt 406, 'please, do not hack'
197
+ end
198
+ end
199
+ end
200
+
201
+ it 'should allow configuring protection options' do
202
+ post "/a"
203
+ assert_equal 406, status
204
+ assert_equal 'please, do not hack', body
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,57 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+
3
+ describe "Dependencies" do
4
+ describe 'when we require a dependency that have another dependency' do
5
+ before do
6
+ @log_level = Tennpipes::Logger::Config[:test]
7
+ @io = StringIO.new
8
+ Tennpipes::Logger::Config[:test] = { :log_level => :error, :stream => @io }
9
+ Tennpipes::Logger.setup!
10
+ end
11
+
12
+ after do
13
+ Tennpipes::Logger::Config[:test] = @log_level
14
+ Tennpipes::Logger.setup!
15
+ end
16
+
17
+ it 'should raise an error without reloading it twice' do
18
+ capture_io do
19
+ assert_raises(RuntimeError) do
20
+ Tennpipes.require_dependencies(
21
+ Tennpipes.root("fixtures/dependencies/a.rb"),
22
+ Tennpipes.root("fixtures/dependencies/b.rb"),
23
+ Tennpipes.root("fixtures/dependencies/c.rb"),
24
+ Tennpipes.root("fixtures/dependencies/d.rb")
25
+ )
26
+ end
27
+ end
28
+ assert_equal 1, D
29
+ assert_match /RuntimeError - SomeThing/, @io.string
30
+ end
31
+
32
+ it 'should resolve dependency problems' do
33
+ capture_io do
34
+ Tennpipes.require_dependencies(
35
+ Tennpipes.root("fixtures/dependencies/a.rb"),
36
+ Tennpipes.root("fixtures/dependencies/b.rb"),
37
+ Tennpipes.root("fixtures/dependencies/c.rb")
38
+ )
39
+ end
40
+ assert_equal ["B", "C"], A_result
41
+ assert_equal "C", B_result
42
+ assert_equal "", @io.string
43
+ end
44
+
45
+ it 'should remove partially loaded constants' do
46
+ capture_io do
47
+ Tennpipes.require_dependencies(
48
+ Tennpipes.root("fixtures/dependencies/circular/e.rb"),
49
+ Tennpipes.root("fixtures/dependencies/circular/f.rb"),
50
+ Tennpipes.root("fixtures/dependencies/circular/g.rb")
51
+ )
52
+ end
53
+ assert_equal ["name"], F.fields
54
+ assert_equal "", @io.string
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,389 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+
3
+ describe "Filters" do
4
+ it 'should filters by accept header' do
5
+ mock_app do
6
+ get '/foo', :provides => [:xml, :js] do
7
+ request.env['HTTP_ACCEPT']
8
+ end
9
+ end
10
+
11
+ get '/foo', {}, { 'HTTP_ACCEPT' => 'application/xml' }
12
+ assert ok?
13
+ assert_equal 'application/xml', body
14
+ assert_equal 'application/xml;charset=utf-8', response.headers['Content-Type']
15
+
16
+ get '/foo.xml'
17
+ assert ok?
18
+ assert_equal 'application/xml;charset=utf-8', response.headers['Content-Type']
19
+
20
+ get '/foo', {}, { 'HTTP_ACCEPT' => 'application/javascript' }
21
+ assert ok?
22
+ assert_equal 'application/javascript', body
23
+ assert_equal 'application/javascript;charset=utf-8', response.headers['Content-Type']
24
+
25
+ get '/foo.js'
26
+ assert ok?
27
+ assert_equal 'application/javascript;charset=utf-8', response.headers['Content-Type']
28
+
29
+ get '/foo', {}, { "HTTP_ACCEPT" => 'text/html' }
30
+ assert_equal 406, status
31
+ end
32
+
33
+ it 'should allow passing & halting in before filters' do
34
+ mock_app do
35
+ controller do
36
+ before { env['QUERY_STRING'] == 'secret' or pass }
37
+ get :index do
38
+ "secret index"
39
+ end
40
+ end
41
+
42
+ controller do
43
+ before { env['QUERY_STRING'] == 'halt' and halt 401, 'go away!' }
44
+ get :index do
45
+ "index"
46
+ end
47
+ end
48
+ end
49
+
50
+ get "/?secret"
51
+ assert_equal "secret index", body
52
+
53
+ get "/?halt"
54
+ assert_equal "go away!", body
55
+ assert_equal 401, status
56
+
57
+ get "/"
58
+ assert_equal "index", body
59
+ end
60
+
61
+ it 'should scope filters in the given controller' do
62
+ mock_app do
63
+ before { @global = 'global' }
64
+ after { @global = nil }
65
+
66
+ controller :foo do
67
+ before { @foo = :foo }
68
+ after { @foo = nil }
69
+ get("/") { [@foo, @bar, @global].compact.join(" ") }
70
+ end
71
+
72
+ get("/") { [@foo, @bar, @global].compact.join(" ") }
73
+
74
+ controller :bar do
75
+ before { @bar = :bar }
76
+ after { @bar = nil }
77
+ get("/") { [@foo, @bar, @global].compact.join(" ") }
78
+ end
79
+ end
80
+
81
+ get "/bar"
82
+ assert_equal "bar global", body
83
+
84
+ get "/foo"
85
+ assert_equal "foo global", body
86
+
87
+ get "/"
88
+ assert_equal "global", body
89
+ end
90
+
91
+ it 'should be able to access params in a before filter' do
92
+ username_from_before_filter = nil
93
+
94
+ mock_app do
95
+ before do
96
+ username_from_before_filter = params[:username]
97
+ end
98
+
99
+ get :users, :with => :username do
100
+ end
101
+ end
102
+ get '/users/josh'
103
+ assert_equal 'josh', username_from_before_filter
104
+ end
105
+
106
+ it 'should be able to access params normally when a before filter is specified' do
107
+ mock_app do
108
+ before { }
109
+ get :index do
110
+ params.inspect
111
+ end
112
+ end
113
+ get '/?test=what'
114
+ assert_equal '{"test"=>"what"}', body
115
+ end
116
+
117
+ it 'should be able to filter based on a path' do
118
+ mock_app do
119
+ before('/') { @test = "#{@test}before"}
120
+ get :index do
121
+ @test
122
+ end
123
+ get :main do
124
+ @test
125
+ end
126
+ end
127
+ get '/'
128
+ assert_equal 'before', body
129
+ get '/main'
130
+ assert_equal '', body
131
+ end
132
+
133
+ it 'should be able to filter based on a symbol' do
134
+ mock_app do
135
+ before(:index) { @test = 'before'}
136
+ get :index do
137
+ @test
138
+ end
139
+ get :main do
140
+ @test
141
+ end
142
+ end
143
+ get '/'
144
+ assert_equal 'before', body
145
+ get '/main'
146
+ assert_equal '', body
147
+ end
148
+
149
+ it 'should be able to filter based on a symbol for a controller' do
150
+ mock_app do
151
+ controller :foo do
152
+ before(:test) { @test = 'foo'}
153
+ get :test do
154
+ @test.to_s + " response"
155
+ end
156
+ end
157
+ controller :bar do
158
+ before(:test) { @test = 'bar'}
159
+ get :test do
160
+ @test.to_s + " response"
161
+ end
162
+ end
163
+ end
164
+ get '/foo/test'
165
+ assert_equal 'foo response', body
166
+ get '/bar/test'
167
+ assert_equal 'bar response', body
168
+ end
169
+
170
+ it 'should be able to filter based on a symbol or path' do
171
+ mock_app do
172
+ before(:index, '/main') { @test = 'before'}
173
+ get :index do
174
+ @test
175
+ end
176
+ get :main do
177
+ @test
178
+ end
179
+ end
180
+ get '/'
181
+ assert_equal 'before', body
182
+ get '/main'
183
+ assert_equal 'before', body
184
+ end
185
+
186
+ it 'should be able to filter based on a symbol or regexp' do
187
+ mock_app do
188
+ before(:index, /main/) { @test = 'before'}
189
+ get :index do
190
+ @test
191
+ end
192
+ get :main do
193
+ @test
194
+ end
195
+ get :profile do
196
+ @test
197
+ end
198
+ end
199
+ get '/'
200
+ assert_equal 'before', body
201
+ get '/main'
202
+ assert_equal 'before', body
203
+ get '/profile'
204
+ assert_equal '', body
205
+ end
206
+
207
+ it 'should be able to filter excluding based on a symbol' do
208
+ mock_app do
209
+ before(:except => :index) { @test = 'before'}
210
+ get :index do
211
+ @test
212
+ end
213
+ get :main do
214
+ @test
215
+ end
216
+ end
217
+ get '/'
218
+ assert_equal '', body
219
+ get '/main'
220
+ assert_equal 'before', body
221
+ end
222
+
223
+ it 'should be able to filter excluding based on a symbol when specify the multiple routes and use nested controller' do
224
+ mock_app do
225
+ controller :test, :nested do
226
+ before(:except => [:test1, :test2]) { @long = 'long'}
227
+ before(:except => [:test1]) { @short = 'short'}
228
+ get :test1 do
229
+ "#{@long} #{@short} normal"
230
+ end
231
+ get :test2 do
232
+ "#{@long} #{@short} normal"
233
+ end
234
+ get :test3 do
235
+ "#{@long} #{@short} normal"
236
+ end
237
+ end
238
+ end
239
+ get '/test/nested/test1'
240
+ assert_equal ' normal', body
241
+ get '/test/nested/test2'
242
+ assert_equal ' short normal', body
243
+ get '/test/nested/test3'
244
+ assert_equal 'long short normal', body
245
+ end
246
+
247
+ it 'should be able to filter based on a request param' do
248
+ mock_app do
249
+ before(:agent => /IE/) { @test = 'before'}
250
+ get :index do
251
+ @test
252
+ end
253
+ end
254
+ get '/'
255
+ assert_equal '', body
256
+ get "/", {}, {'HTTP_USER_AGENT' => 'This is IE'}
257
+ assert_equal 'before', body
258
+ end
259
+
260
+ it 'should be able to filter based on a symbol or path in multiple controller' do
261
+ mock_app do
262
+ controllers :foo do
263
+ before(:index, '/foo/main') { @test = 'before' }
264
+ get :index do
265
+ @test
266
+ end
267
+ get :main do
268
+ @test
269
+ end
270
+ end
271
+ controllers :bar do
272
+ before(:index, '/bar/main') { @test = 'also before' }
273
+ get :index do
274
+ @test
275
+ end
276
+ get :main do
277
+ @test
278
+ end
279
+ end
280
+ end
281
+ get '/foo'
282
+ assert_equal 'before', body
283
+ get '/bar'
284
+ assert_equal 'also before', body
285
+ get '/foo/main'
286
+ assert_equal 'before', body
287
+ get '/bar/main'
288
+ assert_equal 'also before', body
289
+ end
290
+
291
+ it 'should call before filters even if there was no match' do
292
+ test = nil
293
+ mock_app do
294
+ before(:index, '/foo') { test = 'before' }
295
+ get :index do
296
+ ''
297
+ end
298
+ end
299
+ get '/foo'
300
+ assert_equal 'before', test
301
+ end
302
+
303
+ it 'should ensure the call of before_filter at the first time' do
304
+ once = ''
305
+ mock_app do
306
+ before do
307
+ once += 'before'
308
+ end
309
+ get :index do
310
+ raise Exception, 'Oops'
311
+ end
312
+ post :index do
313
+ raise Exception, 'Oops'
314
+ end
315
+ end
316
+
317
+ post '/'
318
+ assert_equal 'before', once
319
+ end
320
+
321
+ it 'should call before filters only once' do
322
+ once = ''
323
+ mock_app do
324
+ error 500 do
325
+ 'error 500'
326
+ end
327
+ before do
328
+ once += 'before'
329
+ end
330
+ get :index do
331
+ raise Exception, 'Oops'
332
+ end
333
+ end
334
+
335
+ get '/'
336
+ assert_equal 'before', once
337
+ end
338
+
339
+ it 'should catch exceptions in before filters' do
340
+ doodle = nil
341
+ mock_app do
342
+ after do
343
+ doodle = 'Been after'
344
+ end
345
+ before do
346
+ raise StandardError, "before"
347
+ end
348
+ get :index do
349
+ doodle = 'Been now'
350
+ end
351
+ error 500 do
352
+ "We broke #{env['sinatra.error'].message}"
353
+ end
354
+ end
355
+
356
+ get '/'
357
+ assert_equal 'We broke before', body
358
+ assert_equal nil, doodle
359
+ end
360
+
361
+ it 'should catch exceptions in after filters if no exceptions caught before' do
362
+ doodle = ''
363
+ mock_app do
364
+ after do
365
+ doodle += ' and after'
366
+ raise StandardError, "after"
367
+ end
368
+ get :foo do
369
+ doodle = 'Been now'
370
+ raise StandardError, "now"
371
+ end
372
+ get :index do
373
+ doodle = 'Been now'
374
+ end
375
+ error 500 do
376
+ "We broke #{env['sinatra.error'].message}"
377
+ end
378
+ end
379
+
380
+ get '/foo'
381
+ assert_equal 'We broke now', body
382
+ assert_equal 'Been now', doodle
383
+
384
+ doodle = ''
385
+ get '/'
386
+ assert_equal 'We broke after', body
387
+ assert_equal 'Been now and after', doodle
388
+ end
389
+ end