rails-prg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.cane +4 -0
  3. data/.gitignore +19 -0
  4. data/.rspec +3 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +44 -0
  8. data/Rakefile +38 -0
  9. data/lib/rails-prg.rb +5 -0
  10. data/lib/rails/prg.rb +8 -0
  11. data/lib/rails/prg/railtie.rb +13 -0
  12. data/lib/rails/prg/redirected_object_controller.rb +84 -0
  13. data/lib/rails/prg/version.rb +5 -0
  14. data/lib/tasks/quality.rake +15 -0
  15. data/rails-prg.gemspec +43 -0
  16. data/script/spec +22 -0
  17. data/spec/dummy/README.rdoc +28 -0
  18. data/spec/dummy/Rakefile +6 -0
  19. data/spec/dummy/app/assets/images/.keep +0 -0
  20. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  21. data/spec/dummy/app/assets/javascripts/error_duplicator.js +2 -0
  22. data/spec/dummy/app/assets/javascripts/error_duplicators.js +2 -0
  23. data/spec/dummy/app/assets/javascripts/example_prgs.js +2 -0
  24. data/spec/dummy/app/assets/javascripts/post_redirect_gets.js +2 -0
  25. data/spec/dummy/app/assets/javascripts/test_objects.js +2 -0
  26. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  27. data/spec/dummy/app/assets/stylesheets/error_duplicator.css +4 -0
  28. data/spec/dummy/app/assets/stylesheets/error_duplicators.css +4 -0
  29. data/spec/dummy/app/assets/stylesheets/example_prgs.css +4 -0
  30. data/spec/dummy/app/assets/stylesheets/post_redirect_gets.css +4 -0
  31. data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
  32. data/spec/dummy/app/assets/stylesheets/test_objects.css +4 -0
  33. data/spec/dummy/app/controllers/application_controller.rb +19 -0
  34. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  35. data/spec/dummy/app/controllers/error_duplicators_controller.rb +64 -0
  36. data/spec/dummy/app/controllers/example_prgs_controller.rb +74 -0
  37. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  38. data/spec/dummy/app/helpers/error_duplicators_helper.rb +2 -0
  39. data/spec/dummy/app/helpers/example_prgs_helper.rb +2 -0
  40. data/spec/dummy/app/mailers/.keep +0 -0
  41. data/spec/dummy/app/models/.keep +0 -0
  42. data/spec/dummy/app/models/concerns/.keep +0 -0
  43. data/spec/dummy/app/models/error_duplicator.rb +3 -0
  44. data/spec/dummy/app/models/example_prg.rb +3 -0
  45. data/spec/dummy/app/views/error_duplicators/_form.html.erb +29 -0
  46. data/spec/dummy/app/views/error_duplicators/edit.html.erb +6 -0
  47. data/spec/dummy/app/views/error_duplicators/index.html.erb +31 -0
  48. data/spec/dummy/app/views/error_duplicators/new.html.erb +5 -0
  49. data/spec/dummy/app/views/error_duplicators/show.html.erb +19 -0
  50. data/spec/dummy/app/views/example_prgs/_form.html.erb +29 -0
  51. data/spec/dummy/app/views/example_prgs/edit.html.erb +6 -0
  52. data/spec/dummy/app/views/example_prgs/index.html.erb +31 -0
  53. data/spec/dummy/app/views/example_prgs/new.html.erb +5 -0
  54. data/spec/dummy/app/views/example_prgs/show.html.erb +19 -0
  55. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  56. data/spec/dummy/config.ru +4 -0
  57. data/spec/dummy/config/application.rb +29 -0
  58. data/spec/dummy/config/boot.rb +5 -0
  59. data/spec/dummy/config/database.yml +25 -0
  60. data/spec/dummy/config/environment.rb +5 -0
  61. data/spec/dummy/config/environments/development.rb +29 -0
  62. data/spec/dummy/config/environments/production.rb +80 -0
  63. data/spec/dummy/config/environments/test.rb +36 -0
  64. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  65. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  66. data/spec/dummy/config/initializers/inflections.rb +16 -0
  67. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  68. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  69. data/spec/dummy/config/initializers/session_store.rb +3 -0
  70. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  71. data/spec/dummy/config/locales/en.yml +23 -0
  72. data/spec/dummy/config/routes.rb +4 -0
  73. data/spec/dummy/db/migrate/20140225004609_create_error_duplicators.rb +12 -0
  74. data/spec/dummy/db/migrate/20140225070319_create_example_prgs.rb +12 -0
  75. data/spec/dummy/db/schema.rb +36 -0
  76. data/spec/dummy/db/structure.sql +9 -0
  77. data/spec/dummy/lib/assets/.keep +0 -0
  78. data/spec/dummy/public/404.html +58 -0
  79. data/spec/dummy/public/422.html +58 -0
  80. data/spec/dummy/public/500.html +57 -0
  81. data/spec/dummy/public/favicon.ico +0 -0
  82. data/spec/rails/prg/features/error_duplication_spec.rb +100 -0
  83. data/spec/rails/prg/features/redirected_objects_spec.rb +92 -0
  84. data/spec/rails/prg/redirected_object_controller_spec.rb +282 -0
  85. data/spec/spec_helper.rb +36 -0
  86. data/spec/support/selenium_display.rb +78 -0
  87. data/spec/support/use_selenium_display.rb +13 -0
  88. data/spec/support/use_simplecov.rb +30 -0
  89. 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