rails_dynamic_errors 0.0.9
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +31 -0
- data/app/controllers/rails_dynamic_errors/errors_controller.rb +52 -0
- data/app/views/rails_dynamic_errors/errors/show.html.erb +4 -0
- data/config/routes.rb +3 -0
- data/lib/engine_helper.rb +15 -0
- data/lib/generators/rails_dynamic_errors/install_generator.rb +38 -0
- data/lib/rails_dynamic_errors/engine.rb +32 -0
- data/lib/rails_dynamic_errors/middleware/dynamic_errors.rb +98 -0
- data/lib/rails_dynamic_errors/version.rb +4 -0
- data/lib/rails_dynamic_errors.rb +11 -0
- data/lib/tasks/rails_dynamic_errors_tasks.rake +4 -0
- data/spec/controllers/errors_controller_spec.rb +128 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/javascripts/booms.js +2 -0
- data/spec/dummy/app/assets/javascripts/things.js +2 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/assets/stylesheets/booms.css +4 -0
- data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
- data/spec/dummy/app/assets/stylesheets/things.css +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/booms_controller.rb +6 -0
- data/spec/dummy/app/controllers/things_controller.rb +58 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/helpers/booms_helper.rb +2 -0
- data/spec/dummy/app/helpers/things_helper.rb +2 -0
- data/spec/dummy/app/models/thing.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/rails_dynamic_errors/errors/url_helpers.html.erb +2 -0
- data/spec/dummy/app/views/things/_form.html.erb +21 -0
- data/spec/dummy/app/views/things/edit.html.erb +6 -0
- data/spec/dummy/app/views/things/index.html.erb +27 -0
- data/spec/dummy/app/views/things/new.html.erb +5 -0
- data/spec/dummy/app/views/things/show.html.erb +9 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +43 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +67 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20140620101702_create_things.rb +9 -0
- data/spec/dummy/db/production.sqlite3 +0 -0
- data/spec/dummy/db/schema.rb +22 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +3309 -0
- data/spec/dummy/log/production.log +35 -0
- data/spec/dummy/log/test.log +30008 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/tmp/config/application.rb +11 -0
- data/spec/dummy/tmp/config/routes.rb +10 -0
- data/spec/features/application_link_helpers_spec.rb +14 -0
- data/spec/features/error_handling_spec.rb +167 -0
- data/spec/lib/generators/rails_dynamic_errors/install_generator_spec.rb +32 -0
- data/spec/lib/rails_dynamic_errors/engine_spec.rb +13 -0
- data/spec/lib/rails_dynamic_errors/middleware/dynamic_errors_spec.rb +171 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/support/error.rb +19 -0
- data/spec/views/errors/show.html.erb_spec.rb +24 -0
- metadata +265 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The page you were looking for doesn't exist (404)</title>
|
5
|
+
<style>
|
6
|
+
body {
|
7
|
+
background-color: #EFEFEF;
|
8
|
+
color: #2E2F30;
|
9
|
+
text-align: center;
|
10
|
+
font-family: arial, sans-serif;
|
11
|
+
}
|
12
|
+
|
13
|
+
div.dialog {
|
14
|
+
width: 25em;
|
15
|
+
margin: 4em auto 0 auto;
|
16
|
+
border: 1px solid #CCC;
|
17
|
+
border-right-color: #999;
|
18
|
+
border-left-color: #999;
|
19
|
+
border-bottom-color: #BBB;
|
20
|
+
border-top: #B00100 solid 4px;
|
21
|
+
border-top-left-radius: 9px;
|
22
|
+
border-top-right-radius: 9px;
|
23
|
+
background-color: white;
|
24
|
+
padding: 7px 4em 0 4em;
|
25
|
+
}
|
26
|
+
|
27
|
+
h1 {
|
28
|
+
font-size: 100%;
|
29
|
+
color: #730E15;
|
30
|
+
line-height: 1.5em;
|
31
|
+
}
|
32
|
+
|
33
|
+
body > p {
|
34
|
+
width: 33em;
|
35
|
+
margin: 0 auto 1em;
|
36
|
+
padding: 1em 0;
|
37
|
+
background-color: #F7F7F7;
|
38
|
+
border: 1px solid #CCC;
|
39
|
+
border-right-color: #999;
|
40
|
+
border-bottom-color: #999;
|
41
|
+
border-bottom-left-radius: 4px;
|
42
|
+
border-bottom-right-radius: 4px;
|
43
|
+
border-top-color: #DADADA;
|
44
|
+
color: #666;
|
45
|
+
box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
|
46
|
+
}
|
47
|
+
</style>
|
48
|
+
</head>
|
49
|
+
|
50
|
+
<body>
|
51
|
+
<!-- This file lives in public/404.html -->
|
52
|
+
<div class="dialog">
|
53
|
+
<h1>The page you were looking for doesn't exist.</h1>
|
54
|
+
<p>You may have mistyped the address or the page may have moved.</p>
|
55
|
+
</div>
|
56
|
+
<p>If you are the application owner check the logs for more information.</p>
|
57
|
+
</body>
|
58
|
+
</html>
|
@@ -0,0 +1,58 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The change you wanted was rejected (422)</title>
|
5
|
+
<style>
|
6
|
+
body {
|
7
|
+
background-color: #EFEFEF;
|
8
|
+
color: #2E2F30;
|
9
|
+
text-align: center;
|
10
|
+
font-family: arial, sans-serif;
|
11
|
+
}
|
12
|
+
|
13
|
+
div.dialog {
|
14
|
+
width: 25em;
|
15
|
+
margin: 4em auto 0 auto;
|
16
|
+
border: 1px solid #CCC;
|
17
|
+
border-right-color: #999;
|
18
|
+
border-left-color: #999;
|
19
|
+
border-bottom-color: #BBB;
|
20
|
+
border-top: #B00100 solid 4px;
|
21
|
+
border-top-left-radius: 9px;
|
22
|
+
border-top-right-radius: 9px;
|
23
|
+
background-color: white;
|
24
|
+
padding: 7px 4em 0 4em;
|
25
|
+
}
|
26
|
+
|
27
|
+
h1 {
|
28
|
+
font-size: 100%;
|
29
|
+
color: #730E15;
|
30
|
+
line-height: 1.5em;
|
31
|
+
}
|
32
|
+
|
33
|
+
body > p {
|
34
|
+
width: 33em;
|
35
|
+
margin: 0 auto 1em;
|
36
|
+
padding: 1em 0;
|
37
|
+
background-color: #F7F7F7;
|
38
|
+
border: 1px solid #CCC;
|
39
|
+
border-right-color: #999;
|
40
|
+
border-bottom-color: #999;
|
41
|
+
border-bottom-left-radius: 4px;
|
42
|
+
border-bottom-right-radius: 4px;
|
43
|
+
border-top-color: #DADADA;
|
44
|
+
color: #666;
|
45
|
+
box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
|
46
|
+
}
|
47
|
+
</style>
|
48
|
+
</head>
|
49
|
+
|
50
|
+
<body>
|
51
|
+
<!-- This file lives in public/422.html -->
|
52
|
+
<div class="dialog">
|
53
|
+
<h1>The change you wanted was rejected.</h1>
|
54
|
+
<p>Maybe you tried to change something you didn't have access to.</p>
|
55
|
+
</div>
|
56
|
+
<p>If you are the application owner check the logs for more information.</p>
|
57
|
+
</body>
|
58
|
+
</html>
|
@@ -0,0 +1,57 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
5
|
+
<style>
|
6
|
+
body {
|
7
|
+
background-color: #EFEFEF;
|
8
|
+
color: #2E2F30;
|
9
|
+
text-align: center;
|
10
|
+
font-family: arial, sans-serif;
|
11
|
+
}
|
12
|
+
|
13
|
+
div.dialog {
|
14
|
+
width: 25em;
|
15
|
+
margin: 4em auto 0 auto;
|
16
|
+
border: 1px solid #CCC;
|
17
|
+
border-right-color: #999;
|
18
|
+
border-left-color: #999;
|
19
|
+
border-bottom-color: #BBB;
|
20
|
+
border-top: #B00100 solid 4px;
|
21
|
+
border-top-left-radius: 9px;
|
22
|
+
border-top-right-radius: 9px;
|
23
|
+
background-color: white;
|
24
|
+
padding: 7px 4em 0 4em;
|
25
|
+
}
|
26
|
+
|
27
|
+
h1 {
|
28
|
+
font-size: 100%;
|
29
|
+
color: #730E15;
|
30
|
+
line-height: 1.5em;
|
31
|
+
}
|
32
|
+
|
33
|
+
body > p {
|
34
|
+
width: 33em;
|
35
|
+
margin: 0 auto 1em;
|
36
|
+
padding: 1em 0;
|
37
|
+
background-color: #F7F7F7;
|
38
|
+
border: 1px solid #CCC;
|
39
|
+
border-right-color: #999;
|
40
|
+
border-bottom-color: #999;
|
41
|
+
border-bottom-left-radius: 4px;
|
42
|
+
border-bottom-right-radius: 4px;
|
43
|
+
border-top-color: #DADADA;
|
44
|
+
color: #666;
|
45
|
+
box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
|
46
|
+
}
|
47
|
+
</style>
|
48
|
+
</head>
|
49
|
+
|
50
|
+
<body>
|
51
|
+
<!-- This file lives in public/500.html -->
|
52
|
+
<div class="dialog">
|
53
|
+
<h1>We're sorry, but something went wrong.</h1>
|
54
|
+
</div>
|
55
|
+
<p>If you are the application owner check the logs for more information.</p>
|
56
|
+
</body>
|
57
|
+
</html>
|
File without changes
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Dummy
|
2
|
+
class Application < Rails::Application
|
3
|
+
# This option is used to set the HTTP error codes for which
|
4
|
+
# rails_dynamic_errors will generate dynamic error pages. A good default
|
5
|
+
# setup is [404, 422], which will catch the two main errors (excluding the
|
6
|
+
# dreaded 500 Internal Server Error) for which Rails provides static HTML
|
7
|
+
# error pages.
|
8
|
+
# config.rails_dynamic_errors.http_error_status_codes_to_handle = [404, 422]
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
|
3
|
+
# This line mounts RailDynamicErrors' routes on the '/errors' path of your
|
4
|
+
# application. This means that any requests to URLs with this prefix in their
|
5
|
+
# path will go to RailsDynamicErrors for processing.
|
6
|
+
#
|
7
|
+
# If you would like to change where this engine is mounted, simply change the
|
8
|
+
# :at option to something different.
|
9
|
+
mount RailsDynamicErrors::Engine, at: '/errors'
|
10
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RailsDynamicErrors::Engine do
|
4
|
+
# Regression test to ensure that the application's URL helpers are available
|
5
|
+
# to the engine. This is necessary because the pages generated by the errors
|
6
|
+
# controller within the engine use the application's layouts, and these may
|
7
|
+
# contain URL helpers for the main application. By default the engine cannot
|
8
|
+
# access these. We can't just use 'main_app.<url_helper>' in the layouts,
|
9
|
+
# either, as that would break the layouts when used in the application.
|
10
|
+
it "should have access to application helpers" do
|
11
|
+
visit '/errors/url_helpers'
|
12
|
+
page.should have_link('New Thing', :href => new_thing_path)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RailsDynamicErrors do
|
4
|
+
context "when the error is manually generated via the errors path" do
|
5
|
+
it "displays the error code" do
|
6
|
+
visit '/errors/invalid_ninja'
|
7
|
+
page.should have_content("invalid_ninja")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context "when the error is automatically generated via the middleware" do
|
12
|
+
before(:each) do
|
13
|
+
Rails.application.config.rails_dynamic_errors.http_error_status_codes_to_handle = []
|
14
|
+
end
|
15
|
+
|
16
|
+
it "does not interfere with valid requests" do
|
17
|
+
thing = Thing.create!(:name => "Test")
|
18
|
+
visit thing_path(thing)
|
19
|
+
page.should have_content("Name: Test")
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when the application is configured to show exceptions" do
|
23
|
+
around(:each) do |example|
|
24
|
+
original = set_environment_variable('action_dispatch.show_exceptions', true)
|
25
|
+
example.run
|
26
|
+
set_environment_variable('action_dispatch.show_exceptions', original)
|
27
|
+
end
|
28
|
+
|
29
|
+
context "and not configured to show detailed exceptions" do
|
30
|
+
around(:each) do |example|
|
31
|
+
original = set_environment_variable('action_dispatch.show_detailed_exceptions', false)
|
32
|
+
example.run
|
33
|
+
set_environment_variable('action_dispatch.show_exceptions', original)
|
34
|
+
end
|
35
|
+
|
36
|
+
context "receives a 404 error" do
|
37
|
+
context "and is configured to handle it" do
|
38
|
+
before(:each) do
|
39
|
+
Rails.application.config.rails_dynamic_errors.http_error_status_codes_to_handle = [404]
|
40
|
+
end
|
41
|
+
|
42
|
+
context "and the error was generated by an invalid route" do
|
43
|
+
it "displays a 404 error page" do
|
44
|
+
visit '/bogus_route'
|
45
|
+
page.should have_content("404 Not Found")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "and the error was generated by a valid route with a non-existent resource" do
|
50
|
+
it "displays a 404 error page" do
|
51
|
+
visit '/things/-1'
|
52
|
+
page.should have_content("404 Not Found")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "and is not configured to handle it" do
|
58
|
+
context "and the error was generated by an invalid route" do
|
59
|
+
it "displays the standard Rails 404 error page" do
|
60
|
+
visit '/bogus_route'
|
61
|
+
page.should_not have_content("404 Not Found")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "and the error was generated by a valid route with a non-existent resource" do
|
66
|
+
it "displays the standard Rails 404 error page" do
|
67
|
+
visit '/things/-1'
|
68
|
+
page.should_not have_content("404 Not Found")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "receives a 500 error" do
|
75
|
+
context "and is configured to handle it" do
|
76
|
+
before(:each) do
|
77
|
+
Rails.application.config.rails_dynamic_errors.http_error_status_codes_to_handle = [500]
|
78
|
+
end
|
79
|
+
|
80
|
+
context "when an internal server error is encountered" do
|
81
|
+
it "displays a 500 error page" do
|
82
|
+
visit '/booms/1'
|
83
|
+
page.should have_content("500 Internal Server Error")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "and is not configured to handle it" do
|
89
|
+
it "displays the standard Rails 500 error page" do
|
90
|
+
visit '/booms/1'
|
91
|
+
page.should_not have_content("500 Internal Server Error")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "and configured to show detailed exceptions" do
|
98
|
+
around(:each) do |example|
|
99
|
+
original = set_environment_variable('action_dispatch.show_detailed_exceptions', true)
|
100
|
+
example.run
|
101
|
+
set_environment_variable('action_dispatch.show_exceptions', original)
|
102
|
+
end
|
103
|
+
|
104
|
+
context "receives a 404 error" do
|
105
|
+
context "and the error was generated by an invalid route" do
|
106
|
+
it "displays the standard Rails 404 error page" do
|
107
|
+
visit '/bogus_route'
|
108
|
+
page.should_not have_content("404 Not Found")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "and the error was generated by a valid route with a non-existent resource" do
|
113
|
+
it "displays the standard Rails 404 error page" do
|
114
|
+
visit '/things/-1'
|
115
|
+
page.should_not have_content("404 Not Found")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "receives a 500 error" do
|
121
|
+
context "when it is not configured to handle 500 errors" do
|
122
|
+
it "displays the standard Rails 500 error page" do
|
123
|
+
visit '/booms/1'
|
124
|
+
page.should_not have_content("500 Internal Server Error")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "when the application is not configured to show exceptions" do
|
132
|
+
around(:each) do |example|
|
133
|
+
original = set_environment_variable('action_dispatch.show_exceptions', false)
|
134
|
+
example.run
|
135
|
+
set_environment_variable('action_dispatch.show_exceptions', original)
|
136
|
+
end
|
137
|
+
|
138
|
+
context "receives a 404 error" do
|
139
|
+
context "and the error was generated by an invalid route" do
|
140
|
+
it "displays the standard Rails 404 error page" do
|
141
|
+
expect { visit '/bogus_route' }.to raise_error
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "and the error was generated by a valid route with a non-existent resource" do
|
146
|
+
it "displays the standard Rails 404 error page" do
|
147
|
+
expect { visit '/things/-1' }.to raise_error
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context "receives a 500 error" do
|
153
|
+
context "when it is not configured to handle 500 errors" do
|
154
|
+
it "displays the standard Rails 500 error page" do
|
155
|
+
expect { visit '/booms/1' }.to raise_error
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def set_environment_variable(variable, value)
|
163
|
+
original_value = Rails.application.env_config[variable]
|
164
|
+
Rails.application.env_config[variable] = value
|
165
|
+
original_value
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'generator_spec'
|
3
|
+
|
4
|
+
describe RailsDynamicErrors::InstallGenerator do
|
5
|
+
destination File.expand_path("../../../../dummy/tmp/", __FILE__)
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
prepare_destination
|
9
|
+
config_dir = File.expand_path("../../../../dummy/tmp/config/", __FILE__)
|
10
|
+
FileUtils.mkdir(config_dir)
|
11
|
+
@config_application_file = File.join(config_dir, 'application.rb')
|
12
|
+
config_routes_file = File.join(config_dir, 'routes.rb')
|
13
|
+
File.open(@config_application_file, 'w') { |f| f.write("module Dummy\n class Application < Rails::Application\n end\nend") }
|
14
|
+
File.open(config_routes_file, 'w') { |f| f.write("Rails.application.routes.draw do\nend") }
|
15
|
+
run_generator
|
16
|
+
end
|
17
|
+
|
18
|
+
it "inserts options into config/application.rb" do
|
19
|
+
text = <<-INSERTION
|
20
|
+
# config.rails_dynamic_errors.http_error_status_codes_to_handle = [404, 422]
|
21
|
+
INSERTION
|
22
|
+
File.read(@config_application_file).should include(text)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "mounts the engine in config/routes.rb" do
|
26
|
+
assert_file "config/routes.rb", /mount RailsDynamicErrors::Engine/
|
27
|
+
end
|
28
|
+
|
29
|
+
it "mounts the engine in config/routes.rb at the 'errors' path" do
|
30
|
+
assert_file "config/routes.rb", /mount RailsDynamicErrors::Engine, at: '#{RailsDynamicErrors::DEFAULT_MOUNT_PATH}'/
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RailsDynamicErrors::Engine do
|
4
|
+
describe "::mounted_at" do
|
5
|
+
it "returns the path at which the engine is mounted within a Rails application" do
|
6
|
+
RailsDynamicErrors::Engine.mounted_at.should eq(RailsDynamicErrors::DEFAULT_MOUNT_PATH)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "creates a set of namespaced configuration options in the Rails application it is mounted within" do
|
10
|
+
Rails.application.config.rails_dynamic_errors.class.should eq(ActiveSupport::OrderedOptions)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RailsDynamicErrors::DynamicErrors do
|
4
|
+
before(:each) do
|
5
|
+
@rails_no_route_response = [404, {'X-Cascade' => 'pass'}, ['Not Found']]
|
6
|
+
@env_options = {}
|
7
|
+
|
8
|
+
# Engine this middleware is contained within is mountable, so we have to take
|
9
|
+
# that into account
|
10
|
+
RailsDynamicErrors::Engine.stub(:mounted_at).and_return('/errors')
|
11
|
+
|
12
|
+
# Prevent the actual Rails application from processing the request
|
13
|
+
Rails.application.routes.stub(:call)
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when the request is local" do
|
17
|
+
before(:each) do
|
18
|
+
@env_options['action_dispatch.show_detailed_exceptions'] = true
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when an exception bubbles up from the Rails application or a middleware further down the stack" do
|
22
|
+
it "re-raises the exception" do
|
23
|
+
exception = ActionController::RoutingError.new("Not Found")
|
24
|
+
app = double("app")
|
25
|
+
app.stub(:call) { raise exception }
|
26
|
+
input_env = env_for('/valid_route/-1', @env_options)
|
27
|
+
middleware = middleware_to_handle_codes(app, [404])
|
28
|
+
expect { middleware.call(input_env) }.to raise_error(exception)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when the response received has a 404 status code and X-Cascade header set to 'pass'" do
|
33
|
+
it "passed on the response" do
|
34
|
+
app = double("app")
|
35
|
+
app.stub(:call).and_return(@rails_no_route_response)
|
36
|
+
input_env = env_for('/invalid_route', @env_options)
|
37
|
+
middleware = middleware_to_handle_codes(app, [404])
|
38
|
+
response = middleware.call(input_env)
|
39
|
+
response.should eq(@rails_no_route_response)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when the request is remote" do
|
45
|
+
before(:each) do
|
46
|
+
@env_options['action_dispatch.show_detailed_exceptions'] = false
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when exceptions should be shown" do
|
50
|
+
before(:each) do
|
51
|
+
@env_options['action_dispatch.show_exceptions'] = true
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when an exception bubbles up from the Rails application or a middleware further down the stack" do
|
55
|
+
before(:each) do
|
56
|
+
@exception = ActionController::RoutingError.new("Not Found")
|
57
|
+
@app = double("app")
|
58
|
+
@app.stub(:call) { raise @exception }
|
59
|
+
@input_env = env_for('/valid_route/-1', @env_options)
|
60
|
+
end
|
61
|
+
|
62
|
+
context "and it is configured to handle the HTTP status code that exception is associated with" do
|
63
|
+
before(:each) do
|
64
|
+
@middleware = middleware_to_handle_codes(@app, [404])
|
65
|
+
end
|
66
|
+
|
67
|
+
it "updates the environment of the request to point to a path that will generate a dynamic error page for the status code" do
|
68
|
+
(code, output_env) = @middleware.call(@input_env)
|
69
|
+
@input_env['PATH_INFO'].should eq('/errors/404')
|
70
|
+
end
|
71
|
+
|
72
|
+
it "updates the environment of the request with the exception that caused the error" do
|
73
|
+
(code, output_env) = @middleware.call(@input_env)
|
74
|
+
@input_env['action_dispatch.exception'].should eq(@exception)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "calls the router of the Rails application it's embedded within to process the updated environment" do
|
78
|
+
Rails.application.routes.should_receive(:call).with(@input_env)
|
79
|
+
(code, output_env) = @middleware.call(@input_env)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "and it is not configured to handle the HTTP status code that exception is associated with" do
|
84
|
+
it "re-raises the exception" do
|
85
|
+
middleware = middleware_to_handle_codes(@app, [])
|
86
|
+
expect { middleware.call(@input_env) }.to raise_error(@exception)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "when the response received has a 404 status code and X-Cascade header set to 'pass'" do
|
92
|
+
before(:each) do
|
93
|
+
@app = double("app")
|
94
|
+
@app.stub(:call).and_return([404, {'X-Cascade' => 'pass'}, ['Not Found']])
|
95
|
+
@input_env = env_for('/invalid_route', @env_options)
|
96
|
+
end
|
97
|
+
|
98
|
+
context "and it is configured to handle 404 status codes" do
|
99
|
+
before(:each) do
|
100
|
+
@middleware = middleware_to_handle_codes(@app, [404])
|
101
|
+
end
|
102
|
+
|
103
|
+
it "updates the environment of the request to point to a path that will generate a dynamic error page for the status code" do
|
104
|
+
(code, output_env) = @middleware.call(@input_env)
|
105
|
+
@input_env['PATH_INFO'].should eq('/errors/404')
|
106
|
+
end
|
107
|
+
|
108
|
+
it "updates the environment of the request with a routing exception" do
|
109
|
+
(code, output_env) = @middleware.call(@input_env)
|
110
|
+
@input_env['action_dispatch.exception'].class.should eq(ActionController::RoutingError)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "calls the router of the Rails application it's embedded within to process the updated environment" do
|
114
|
+
Rails.application.routes.should_receive(:call).with(@input_env)
|
115
|
+
(code, output_env) = @middleware.call(@input_env)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "and it is not configured to handle 404 status codes" do
|
120
|
+
it "passes on the response" do
|
121
|
+
middleware = middleware_to_handle_codes(@app, [])
|
122
|
+
response = middleware.call(@input_env)
|
123
|
+
response.should eq([404, {'X-Cascade' => 'pass'}, ['Not Found']])
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "when exceptions should be raised" do
|
130
|
+
before(:each) do
|
131
|
+
@env_options['action_dispatch.show_exceptions'] = false
|
132
|
+
end
|
133
|
+
|
134
|
+
context "when an exception bubbles up from the Rails application or a middleware further down the stack" do
|
135
|
+
it "re-raises the exception" do
|
136
|
+
exception = ActionController::RoutingError.new("Not Found")
|
137
|
+
app = double("app")
|
138
|
+
app.stub(:call) { raise exception }
|
139
|
+
input_env = env_for('/valid_route/-1', @env_options)
|
140
|
+
middleware = middleware_to_handle_codes(app, [404])
|
141
|
+
expect { middleware.call(input_env) }.to raise_error(exception)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "when the response received has a 404 status code and X-Cascade header set to 'pass'" do
|
146
|
+
it "passes on the response" do
|
147
|
+
app = double("app")
|
148
|
+
app.stub(:call).and_return([404, {'X-Cascade' => 'pass'}, ['Not Found']])
|
149
|
+
input_env = env_for('/invalid_route', @env_options)
|
150
|
+
middleware = middleware_to_handle_codes(app, [])
|
151
|
+
response = middleware.call(input_env)
|
152
|
+
response.should eq([404, {'X-Cascade' => 'pass'}, ['Not Found']])
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def middleware_to_handle_codes(app, codes)
|
159
|
+
handle_codes(codes)
|
160
|
+
RailsDynamicErrors::DynamicErrors.new(app)
|
161
|
+
end
|
162
|
+
|
163
|
+
def handle_codes(codes)
|
164
|
+
Rails.application.config.rails_dynamic_errors.http_error_status_codes_to_handle = codes
|
165
|
+
end
|
166
|
+
|
167
|
+
def env_for(url, options = {})
|
168
|
+
env = Rack::MockRequest.env_for(url, options)
|
169
|
+
env
|
170
|
+
end
|
171
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# This file is copied to spec/ when you run 'rails generate rspec:install'
|
2
|
+
ENV["RAILS_ENV"] ||= 'test'
|
3
|
+
require File.expand_path("../dummy/config/environment", __FILE__)
|
4
|
+
require 'rspec/rails'
|
5
|
+
require 'rspec/autorun'
|
6
|
+
require 'capybara/rspec'
|
7
|
+
|
8
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
9
|
+
# in spec/support/ and its subdirectories.
|
10
|
+
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
|
11
|
+
|
12
|
+
# Checks for pending migrations before tests are run.
|
13
|
+
# If you are not using ActiveRecord, you can remove this line.
|
14
|
+
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
|
15
|
+
|
16
|
+
RSpec.configure do |config|
|
17
|
+
# ## Mock Framework
|
18
|
+
#
|
19
|
+
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
|
20
|
+
#
|
21
|
+
# config.mock_with :mocha
|
22
|
+
# config.mock_with :flexmock
|
23
|
+
# config.mock_with :rr
|
24
|
+
|
25
|
+
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
26
|
+
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
27
|
+
|
28
|
+
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
29
|
+
# examples within a transaction, remove the following line or assign false
|
30
|
+
# instead of true.
|
31
|
+
config.use_transactional_fixtures = true
|
32
|
+
|
33
|
+
# If true, the base class of anonymous controllers will be inferred
|
34
|
+
# automatically. This will be the default behavior in future versions of
|
35
|
+
# rspec-rails.
|
36
|
+
config.infer_base_class_for_anonymous_controllers = false
|
37
|
+
|
38
|
+
# Run specs in random order to surface order dependencies. If you find an
|
39
|
+
# order dependency and want to debug it, you can fix the order by providing
|
40
|
+
# the seed, which is printed after each run.
|
41
|
+
# --seed 1234
|
42
|
+
config.order = "random"
|
43
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# From ActionDispatch::ExceptionWrapper
|
2
|
+
HTTP_STATUS_CODE_RAILS_EXCEPTIONS = {
|
3
|
+
400 => ActionController::BadRequest ,
|
4
|
+
# 400 => ActionDispatch::ParamsParser::ParseError ,
|
5
|
+
# 400 => ActionController::ParameterMissing ,
|
6
|
+
404 => ActionController::RoutingError ,
|
7
|
+
# 404 => AbstractController::ActionNotFound ,
|
8
|
+
405 => ActionController::MethodNotAllowed ,
|
9
|
+
# 405 => ActionController::UnknownHttpMethod ,
|
10
|
+
406 => ActionController::UnknownFormat ,
|
11
|
+
422 => ActionController::InvalidAuthenticityToken,
|
12
|
+
501 => ActionController::NotImplemented ,
|
13
|
+
}
|
14
|
+
|
15
|
+
def build_environment_after_exception_for_status_code(status_code, message = nil)
|
16
|
+
@exception = HTTP_STATUS_CODE_RAILS_EXCEPTIONS.fetch(status_code, Exception).new(message)
|
17
|
+
controller.env["PATH_INFO"] = "/#{status_code}"
|
18
|
+
controller.env["action_dispatch.exception"] = @exception
|
19
|
+
end
|