rails-prg 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|