rails-prg 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.cane +4 -0
- data/.gitignore +19 -0
- data/.rspec +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +44 -0
- data/Rakefile +38 -0
- data/lib/rails-prg.rb +5 -0
- data/lib/rails/prg.rb +8 -0
- data/lib/rails/prg/railtie.rb +13 -0
- data/lib/rails/prg/redirected_object_controller.rb +84 -0
- data/lib/rails/prg/version.rb +5 -0
- data/lib/tasks/quality.rake +15 -0
- data/rails-prg.gemspec +43 -0
- data/script/spec +22 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/javascripts/error_duplicator.js +2 -0
- data/spec/dummy/app/assets/javascripts/error_duplicators.js +2 -0
- data/spec/dummy/app/assets/javascripts/example_prgs.js +2 -0
- data/spec/dummy/app/assets/javascripts/post_redirect_gets.js +2 -0
- data/spec/dummy/app/assets/javascripts/test_objects.js +2 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/assets/stylesheets/error_duplicator.css +4 -0
- data/spec/dummy/app/assets/stylesheets/error_duplicators.css +4 -0
- data/spec/dummy/app/assets/stylesheets/example_prgs.css +4 -0
- data/spec/dummy/app/assets/stylesheets/post_redirect_gets.css +4 -0
- data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
- data/spec/dummy/app/assets/stylesheets/test_objects.css +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +19 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/controllers/error_duplicators_controller.rb +64 -0
- data/spec/dummy/app/controllers/example_prgs_controller.rb +74 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/helpers/error_duplicators_helper.rb +2 -0
- data/spec/dummy/app/helpers/example_prgs_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/models/error_duplicator.rb +3 -0
- data/spec/dummy/app/models/example_prg.rb +3 -0
- data/spec/dummy/app/views/error_duplicators/_form.html.erb +29 -0
- data/spec/dummy/app/views/error_duplicators/edit.html.erb +6 -0
- data/spec/dummy/app/views/error_duplicators/index.html.erb +31 -0
- data/spec/dummy/app/views/error_duplicators/new.html.erb +5 -0
- data/spec/dummy/app/views/error_duplicators/show.html.erb +19 -0
- data/spec/dummy/app/views/example_prgs/_form.html.erb +29 -0
- data/spec/dummy/app/views/example_prgs/edit.html.erb +6 -0
- data/spec/dummy/app/views/example_prgs/index.html.erb +31 -0
- data/spec/dummy/app/views/example_prgs/new.html.erb +5 -0
- data/spec/dummy/app/views/example_prgs/show.html.erb +19 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +29 -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 +4 -0
- data/spec/dummy/db/migrate/20140225004609_create_error_duplicators.rb +12 -0
- data/spec/dummy/db/migrate/20140225070319_create_example_prgs.rb +12 -0
- data/spec/dummy/db/schema.rb +36 -0
- data/spec/dummy/db/structure.sql +9 -0
- data/spec/dummy/lib/assets/.keep +0 -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/rails/prg/features/error_duplication_spec.rb +100 -0
- data/spec/rails/prg/features/redirected_objects_spec.rb +92 -0
- data/spec/rails/prg/redirected_object_controller_spec.rb +282 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/support/selenium_display.rb +78 -0
- data/spec/support/use_selenium_display.rb +13 -0
- data/spec/support/use_simplecov.rb +30 -0
- metadata +392 -0
File without changes
|
@@ -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,100 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
feature "Standard Rails render on errors" do
|
4
|
+
let(:existing_example) { ErrorDuplicator.create(subject: 'anything', body: 'test body', published: true) }
|
5
|
+
|
6
|
+
scenario "ensure secure environment for accurate test" do
|
7
|
+
# Check that environment tested is actually secure (without selenium)
|
8
|
+
visit new_error_duplicator_path
|
9
|
+
expect(page.response_headers["Cache-Control"]).to include("no-cache, no-store")
|
10
|
+
end
|
11
|
+
|
12
|
+
scenario "triggering browser cache error in secure environment with browser history disabled", js: true do
|
13
|
+
ErrorDuplicator.count.should eq(0)
|
14
|
+
|
15
|
+
# Create new with an error
|
16
|
+
visit new_error_duplicator_path
|
17
|
+
fill_in "Subject", :with => existing_example.subject
|
18
|
+
click_button "Create Error duplicator"
|
19
|
+
expect(page).to have_text("Subject has already been taken")
|
20
|
+
|
21
|
+
# Should have set the error on the object
|
22
|
+
expect(page).to have_field('Subject', with: existing_example.subject)
|
23
|
+
|
24
|
+
# Should *not* have redirected back
|
25
|
+
expect(page.current_path).to eq(error_duplicators_path)
|
26
|
+
|
27
|
+
# Should create successfully following an error
|
28
|
+
fill_in "Subject", :with => "testing NEW input"
|
29
|
+
click_button "Create Error duplicator"
|
30
|
+
expect(page).to have_text("Error duplicator was successfully created.")
|
31
|
+
|
32
|
+
ErrorDuplicator.count.should eq(2)
|
33
|
+
|
34
|
+
# On click of back button
|
35
|
+
page.execute_script("window.history.back();")
|
36
|
+
|
37
|
+
# Cache miss error displayed for specific browser
|
38
|
+
case $selenium_display.browser.to_sym
|
39
|
+
when :firefox
|
40
|
+
expect(page.find("h1#errorTitleText")).to have_text("Document Expired")
|
41
|
+
expect(page.find("p#errorShortDescText")).to have_text("This document is no longer available.")
|
42
|
+
expect(page.find("div#errorLongDesc")).to have_text("The requested document is not available in Firefox's cache")
|
43
|
+
expect(page.current_path).to eq(error_duplicators_path)
|
44
|
+
when :chrome
|
45
|
+
within "div#main-frame-error" do
|
46
|
+
expect(page.find("h1")).to have_text("Confirm Form Resubmission")
|
47
|
+
click_button "More" #triggers chrome to load error code
|
48
|
+
expect(page.find("div.error-code")).to have_text("Error code: ERR_CACHE_MISS")
|
49
|
+
end
|
50
|
+
else
|
51
|
+
raise "Error - Unhandled browser"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
scenario "ensure non-secure environment for accurate test" do
|
56
|
+
# Check that environment tested is not secure (without selenium)
|
57
|
+
visit edit_error_duplicator_path(existing_example)
|
58
|
+
expect(page.response_headers["Cache-Control"]).not_to include("no-cache, no-store")
|
59
|
+
end
|
60
|
+
|
61
|
+
scenario "working normally in non-secure environment with browser history", js: true do
|
62
|
+
# Edit page has no secure headers set
|
63
|
+
visit edit_error_duplicator_path(existing_example)
|
64
|
+
|
65
|
+
fill_in "Subject", :with => ""
|
66
|
+
click_button "Update Error duplicator"
|
67
|
+
expect(page).to have_text("Subject can't be blank")
|
68
|
+
expect(page).to have_field('Subject', with: "")
|
69
|
+
expect(page.current_path).to eq(error_duplicator_path(existing_example))
|
70
|
+
|
71
|
+
# Edit successfully
|
72
|
+
fill_in "Subject", :with => "updated test input"
|
73
|
+
click_button "Update Error duplicator"
|
74
|
+
expect(page).to have_text("Error duplicator was successfully updated.")
|
75
|
+
|
76
|
+
# Should *not* have redirected back
|
77
|
+
expect(page.current_path).to eq(error_duplicator_path(existing_example))
|
78
|
+
|
79
|
+
# On click of back button
|
80
|
+
page.execute_script("window.history.back();")
|
81
|
+
|
82
|
+
# Browser specific way of handling 'back' with errors in non-secure environment
|
83
|
+
case $selenium_display.browser.to_sym
|
84
|
+
when :firefox
|
85
|
+
# Backs all the way back to edit page without errors (pre-post)
|
86
|
+
expect(page.current_path).to eq(edit_error_duplicator_path(existing_example))
|
87
|
+
page.should have_content("Editing error_duplicator")
|
88
|
+
expect(page).to_not have_text("Subject can't be blank")
|
89
|
+
expect(page).to have_field('Subject', with: "") #Posted value
|
90
|
+
when :chrome
|
91
|
+
# Backs all the way back to show page with errors (post -> rendered error)
|
92
|
+
expect(page.current_path).to eq(error_duplicator_path(existing_example))
|
93
|
+
page.should have_content("Editing error_duplicator")
|
94
|
+
expect(page).to have_text("Subject can't be blank")
|
95
|
+
expect(page).to have_field('Subject', with: "updated test input") #updated value
|
96
|
+
else
|
97
|
+
raise "Error - Unhandled browser"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
feature "Use full post-redirect-get displaying original params and errors on redirect" do
|
4
|
+
let(:existing_example) { ExamplePrg.create(subject: 'existing test input', body: 'test body', published: true) }
|
5
|
+
|
6
|
+
scenario "ensure secure environment for accurate test" do
|
7
|
+
# Check that environment tested is actually secure (without selenium)
|
8
|
+
visit new_error_duplicator_path
|
9
|
+
expect(page.response_headers["Cache-Control"]).to include("no-cache, no-store")
|
10
|
+
end
|
11
|
+
|
12
|
+
scenario "within a secure environment with browser history disallowed", js: true do
|
13
|
+
ExamplePrg.count.should eq(0)
|
14
|
+
|
15
|
+
# Create error
|
16
|
+
visit new_example_prg_path
|
17
|
+
fill_in "Subject", :with => existing_example.subject
|
18
|
+
click_button "Create Example prg"
|
19
|
+
expect(page).to have_text("Subject has already been taken")
|
20
|
+
|
21
|
+
# Should have set the error on the object
|
22
|
+
expect(page).to have_field('Subject', with: existing_example.subject)
|
23
|
+
|
24
|
+
# Should have redirected back
|
25
|
+
expect(page.current_path).to eq(new_example_prg_path)
|
26
|
+
|
27
|
+
# Should create successfully following error
|
28
|
+
fill_in "Subject", :with => "testing NEW input"
|
29
|
+
click_button "Create Example prg"
|
30
|
+
expect(page).to have_text("Example prg was successfully created.")
|
31
|
+
|
32
|
+
ExamplePrg.count.should eq(2)
|
33
|
+
|
34
|
+
# On click of back button
|
35
|
+
page.execute_script("window.history.back();")
|
36
|
+
|
37
|
+
# Should go back to a blank 'new' page
|
38
|
+
expect(page).to have_text("New example_prg")
|
39
|
+
expect(page.current_path).to eq(new_example_prg_path)
|
40
|
+
expect(page).not_to have_text("Subject has already been taken") #no errors
|
41
|
+
|
42
|
+
# Browser specific redirection
|
43
|
+
case $selenium_display.browser.to_sym
|
44
|
+
when :firefox
|
45
|
+
# Backs to the new page being completely empty
|
46
|
+
expect(page).to have_field('Subject', with: "")
|
47
|
+
when :chrome
|
48
|
+
# Backs to the new page with original entries already loaded
|
49
|
+
expect(page).to have_field('Subject', with: "testing NEW input")
|
50
|
+
else
|
51
|
+
raise "Error - Unhandled browser"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
scenario "ensure normal browser history environment for accurate test" do
|
56
|
+
# Check that environment tested is not secure
|
57
|
+
# -> Selenium driver cannot check response headers
|
58
|
+
visit edit_example_prg_path(existing_example)
|
59
|
+
expect(page.response_headers["Cache-Control"]).not_to include("no-cache, no-store")
|
60
|
+
end
|
61
|
+
|
62
|
+
scenario "within a normal browser history environment", js: true do
|
63
|
+
# Edit page has no secure headers set
|
64
|
+
visit edit_example_prg_path(existing_example)
|
65
|
+
|
66
|
+
# Create error
|
67
|
+
fill_in "Subject", :with => ""
|
68
|
+
click_button "Update Example prg"
|
69
|
+
|
70
|
+
# Should redirect back to edit page with errors
|
71
|
+
expect(page.current_path).to eq(edit_example_prg_path(existing_example))
|
72
|
+
expect(page).to have_text("Subject can't be blank")
|
73
|
+
expect(page).to have_field('Subject', with: "")
|
74
|
+
|
75
|
+
# Edit successfully
|
76
|
+
fill_in "Subject", :with => "updated test input"
|
77
|
+
click_button "Update Example prg"
|
78
|
+
expect(page).to have_text("Example prg was successfully updated.")
|
79
|
+
|
80
|
+
# Should have redirected back
|
81
|
+
expect(page.current_path).to eq(example_prg_path(existing_example))
|
82
|
+
|
83
|
+
# On click of back button
|
84
|
+
page.execute_script("window.history.back();")
|
85
|
+
|
86
|
+
# Should have redirected back to edit page with errors
|
87
|
+
expect(page.current_path).to eq(edit_example_prg_path(existing_example))
|
88
|
+
expect(page).to have_text("Subject can't be blank")
|
89
|
+
expect(page).to have_field('Subject', with: "updated test input")
|
90
|
+
expect(page).to have_field('Published', with: 1)
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,282 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
#require "action_controller"
|
3
|
+
|
4
|
+
describe ExamplePrgsController, type: :controller do
|
5
|
+
|
6
|
+
describe "post redirect get with error conditions" do
|
7
|
+
# Example Post-Redirect-Get on error conditions
|
8
|
+
# without Rails error->render pattern
|
9
|
+
class TestObject
|
10
|
+
include ActiveModel::Validations
|
11
|
+
attr_accessor :some_field
|
12
|
+
attr_reader :protected_field, :private_field
|
13
|
+
|
14
|
+
def initialize(passed_attributes = {})
|
15
|
+
self.some_field = passed_attributes[:some_field] if passed_attributes
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def protected_field=(value)
|
21
|
+
@protected_field = value #Shouldn't allow this
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def private_field=(value)
|
27
|
+
@private_field = value #Shouldn't allow this
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
controller(ExamplePrgsController) do
|
32
|
+
def new
|
33
|
+
safe_params = [
|
34
|
+
:some_field, :set_redirected_flash,
|
35
|
+
:protected_field, :private_field
|
36
|
+
]
|
37
|
+
fake_flash_for_test(safe_params)
|
38
|
+
|
39
|
+
@object = TestObject.new(params.permit(*safe_params))
|
40
|
+
|
41
|
+
load_redirected_objects!
|
42
|
+
|
43
|
+
render text: 'successful load'
|
44
|
+
end
|
45
|
+
|
46
|
+
def create
|
47
|
+
@object = TestObject.new(create_params)
|
48
|
+
|
49
|
+
if params.delete(:error)
|
50
|
+
@object.errors.add(:some_field, "not present")
|
51
|
+
set_redirected_object!('@object', @object, create_params)
|
52
|
+
redirect_to '/back_to_new_page'
|
53
|
+
else
|
54
|
+
redirect_to '/successful_result'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def create_params
|
61
|
+
@create_params ||= begin
|
62
|
+
if params.delete(:with_strong_parameters)
|
63
|
+
params.require(:object).permit(:some_field)
|
64
|
+
else
|
65
|
+
#Unsafe parameters
|
66
|
+
params[:object]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# As request hasn't happened in test yet,
|
72
|
+
# we must set flash manually that would handle redirected objects
|
73
|
+
# This duplicates the behaviour for unit testing 'after' a redirect
|
74
|
+
def fake_flash_for_test(allowed_params)
|
75
|
+
if params[:set_redirected_flash]
|
76
|
+
content_for_flash = JSON.parse(params[:set_redirected_flash], symbolize_names: true)
|
77
|
+
flash[:redirected_objects] = if params.delete(:raw_hash)
|
78
|
+
# Checking if a developer has passed raw hashes instead
|
79
|
+
# of full parameters hash with permitted attributes
|
80
|
+
content_for_flash
|
81
|
+
else
|
82
|
+
object_params = content_for_flash[:@object][:params]
|
83
|
+
if object_params
|
84
|
+
# Ensure params are set as proper parameters object like they
|
85
|
+
# should be in controller before
|
86
|
+
controller_params = ActionController::Parameters.new(object_params).permit(*allowed_params)
|
87
|
+
content_for_flash[:@object][:params] = controller_params
|
88
|
+
end
|
89
|
+
content_for_flash
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "on change" do
|
96
|
+
context "when error occurs with unpermitted params" do
|
97
|
+
let(:params) do
|
98
|
+
{
|
99
|
+
error: true,
|
100
|
+
object: {
|
101
|
+
unknown_field: 'scary unsafe value',
|
102
|
+
another_unknown: 'field'
|
103
|
+
}
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
context "with submission" do
|
108
|
+
it "should raise error with descriptive error message for faster debugging" do
|
109
|
+
expect { post :create, params }.to raise_error { |exception_received|
|
110
|
+
exception_received.should be_a(RuntimeError)
|
111
|
+
exception_received.to_s.should eq(
|
112
|
+
'[Rails::Prg] Error - Must use permitted strong parameters. Unsafe: unknown_field, another_unknown'
|
113
|
+
)
|
114
|
+
}
|
115
|
+
# Must use curly braces https://github.com/rspec/rspec-expectations/commit/dd5ee3aba1eb33b3dacc56a12964e48a0d2c84f5
|
116
|
+
# Until rspec-expectations 3+ is used
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when error occurs for permitted params" do
|
122
|
+
let(:params) { { error: true, with_strong_parameters: true, object: { some_field: 'input value'} } }
|
123
|
+
|
124
|
+
before do
|
125
|
+
post :create, params
|
126
|
+
end
|
127
|
+
subject { response }
|
128
|
+
|
129
|
+
it { should redirect_to '/back_to_new_page' }
|
130
|
+
|
131
|
+
context "flash for redirected objects" do
|
132
|
+
subject { flash[:redirected_objects] }
|
133
|
+
|
134
|
+
it "should set required attributes" do
|
135
|
+
subject.should eq(
|
136
|
+
{
|
137
|
+
'@object' => {
|
138
|
+
errors: { some_field: ["not present"] },
|
139
|
+
params: { "some_field" => "input value" }
|
140
|
+
}
|
141
|
+
}
|
142
|
+
)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context "when no error has occured" do
|
148
|
+
let(:params) { {} }
|
149
|
+
before do
|
150
|
+
post :create, params
|
151
|
+
end
|
152
|
+
subject { response }
|
153
|
+
|
154
|
+
it { should redirect_to '/successful_result' }
|
155
|
+
|
156
|
+
context "flash error" do
|
157
|
+
subject { flash[:redirected_objects] }
|
158
|
+
|
159
|
+
it { should_not be_present }
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "after a redirect" do
|
165
|
+
context "after an error has occured" do
|
166
|
+
before do
|
167
|
+
get :new, params
|
168
|
+
end
|
169
|
+
subject { controller.instance_variable_get(:@object) }
|
170
|
+
|
171
|
+
let(:object_errors) { { some_field: ["not present"] } }
|
172
|
+
let(:object_params) { { some_field: "inputted value" } }
|
173
|
+
|
174
|
+
let(:redirected_flash) do
|
175
|
+
{
|
176
|
+
'@object' => {
|
177
|
+
errors: object_errors,
|
178
|
+
params: object_params
|
179
|
+
}
|
180
|
+
}
|
181
|
+
end
|
182
|
+
let(:params) { { set_redirected_flash: redirected_flash.to_json } }
|
183
|
+
its(:errors) { should be_an_instance_of(ActiveModel::Errors) }
|
184
|
+
|
185
|
+
it "should have applied the errors to the object for display" do
|
186
|
+
subject.errors.messages.should eq(object_errors)
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should have applied any values passed in previous form" do
|
190
|
+
subject.some_field.should eq("inputted value")
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should have removed the collection from the flash object" do
|
194
|
+
flash[:redirected_objects].should be_blank
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context "when a developer sends unsafe parameters" do
|
199
|
+
let(:object_errors) { { some_field: ["not present"] } }
|
200
|
+
let(:object_params) { { some_field: "inputted value" } }
|
201
|
+
let(:params) { { raw_hash: true, set_redirected_flash: redirected_flash.to_json } }
|
202
|
+
let(:redirected_flash) do
|
203
|
+
{
|
204
|
+
'@object' => {
|
205
|
+
errors: object_errors,
|
206
|
+
params: object_params
|
207
|
+
}
|
208
|
+
}
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'should raise an error' do
|
212
|
+
# Must be curly braces https://github.com/rspec/rspec-expectations/commit/dd5ee3aba1eb33b3dacc56a12964e48a0d2c84f5
|
213
|
+
# do...end blocks for raise_error are ignored...
|
214
|
+
# Until rspec-expectations 3+ is used
|
215
|
+
expect { get :new, params }.to raise_error { |exception_received|
|
216
|
+
exception_received.should be_a(RuntimeError)
|
217
|
+
exception_received.to_s.should eq('[Rails::Prg] Error - Must pass strong parameters.')
|
218
|
+
}
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'should always clear the flash' do
|
222
|
+
expect { get :new, params }.to raise_error
|
223
|
+
flash[:redirected_objects].should be_blank
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should set errors on to the object" do
|
227
|
+
expect { get :new, params }.to raise_error
|
228
|
+
controller.instance_variable_get(:@object).errors.should be_an_instance_of(ActiveModel::Errors)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
context "when attempting to assign illegal fields" do
|
233
|
+
let(:params) { { set_redirected_flash: redirected_flash.to_json } }
|
234
|
+
let(:redirected_flash) do
|
235
|
+
{
|
236
|
+
'@object' => {
|
237
|
+
errors: {},
|
238
|
+
params: object_params
|
239
|
+
}
|
240
|
+
}
|
241
|
+
end
|
242
|
+
|
243
|
+
context "assigning on to object" do
|
244
|
+
context "protected fields" do
|
245
|
+
let(:object_params) { { protected_field: 'protected value' } }
|
246
|
+
|
247
|
+
it "should raise an error on assignment" do
|
248
|
+
expect { get :new, params }.to raise_error { |exception_received|
|
249
|
+
exception_received.should be_a(NoMethodError)
|
250
|
+
exception_received.to_s.should include("protected method `protected_field=' called for")
|
251
|
+
}
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
context "private fields" do
|
256
|
+
let(:object_params) { { private_field: 'private value' } }
|
257
|
+
|
258
|
+
it "should raise an error on assignment" do
|
259
|
+
expect { get :new, params }.to raise_error { |exception_received|
|
260
|
+
exception_received.should be_a(NoMethodError)
|
261
|
+
exception_received.to_s.should include("private method `private_field=' called for")
|
262
|
+
}
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
context "when no error has occured" do
|
270
|
+
let(:redirected_flash) { nil }
|
271
|
+
let(:params) { nil }
|
272
|
+
|
273
|
+
before do
|
274
|
+
get :new, params
|
275
|
+
end
|
276
|
+
|
277
|
+
subject { controller.instance_variable_get(:@object) }
|
278
|
+
|
279
|
+
its(:errors) { should be_empty }
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|