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.
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