rails-prg 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1b012c70c0e0c73ddad3f874e4e9da3530fa5ee4
4
- data.tar.gz: b0ff3de2236d99c9df5806101d3d5761fd134da3
3
+ metadata.gz: 7001387315853fd2a5f4ed982d38bce8624e1d50
4
+ data.tar.gz: 64f20b19d5805a5c45b8333d7f82d6a169cd8f3f
5
5
  SHA512:
6
- metadata.gz: 6bc32193437e830f0120fcb49e1b2140b45b2918b248777515e13aec01fc808e22b1dbe03e190b704050db46e70b1e162d807481ce6d1d7b0540b75cb846cff7
7
- data.tar.gz: 3928df8b355fe672b452f3dd5a1a7f0fc5682ab67410776e7ea15468f29e98a535ec48f31033892658499a5f7c368e2ed4bbdaccbfa5ebf610db4668ba2155d9
6
+ metadata.gz: 75d6312e398a2622088b814ae631ab30c823fac238d3d5a2c4038b3f285f3e64b8bb524f7b15394bfbf86233dfc49f12ec9ca6ca83b07ef175dde59b453b208c
7
+ data.tar.gz: 39f636a5e8e9e7227b6114c00ab20ddd5fdbcf8bbf94e1f3093b5f04fddea9ce54fb782d04d9d06fa5705d77c8c229888919e8166b3d1f2c2e75ae6db100d448
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ .env
1
2
  *.gem
2
3
  *.rbc
3
4
  .bundle
@@ -15,5 +16,7 @@ spec/reports
15
16
  test/tmp
16
17
  test/version_tmp
17
18
  tmp
19
+ sauce_connect.log*
20
+ sauce_connect.ready
18
21
  spec/dummy/log
19
22
  spec/dummy/db/*.sqlite3
@@ -0,0 +1,18 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+
5
+ addons:
6
+ sauce_connect:
7
+ username: rails-prg
8
+ access_key:
9
+ secure: "gN4mKYJjPHGM8L8xl5hEE0mlQ9u1V8AZJlxCPavg7EBe6324FZe6uvN6upuBTr1KCQ1NGUBbzUwurmVAracHxnm3Ctg4gOXSs69e+bGxx1GKQRDHyMYr9+nKrWPML8HtlR2HwS2njDtUZ/q8WMwBQxP4yUwZ8wjueB0yDGVkxXc="
10
+
11
+ before_install:
12
+ - uname -a
13
+ - "export USE_SAUCE=true"
14
+ - "export DISPLAY=:99.0"
15
+ - "sh -e /etc/init.d/xvfb start"
16
+
17
+ script:
18
+ - ./script/spec
data/README.md CHANGED
@@ -1,6 +1,38 @@
1
- # Rails::Prg
1
+ # Rails::Prg (post-redirect-get)
2
2
 
3
- TODO: Write a gem description
3
+ [![Build Status](https://travis-ci.org/tommeier/rails-prg.png)](https://travis-ci.org/tommeier/rails-prg)
4
+ [![Selenium Test Status](https://saucelabs.com/buildstatus/rails-prg)](https://saucelabs.com/u/rails-prg)
5
+ [![Selenium Test Status](https://saucelabs.com/browser-matrix/rails-prg.svg)](https://saucelabs.com/u/rails-prg)
6
+
7
+ Secure applications disable browser history and internal cache. Unfortunately, this causes problems with most browsers when following the standard Rails pattern for displaying errors.
8
+
9
+ We never really see an issue as Rails developers because we usually allow browser-history and internal store. This gem is ***only*** required when `no-cache, no-store` is applied in your headers for a secure application.
10
+
11
+ Standard Rails method for error handling:
12
+ * POST form
13
+ * Error generated -> Render same action
14
+ * POST form
15
+ * No errors -> Redirect to successful action
16
+
17
+ At this point, and the back button is pressed; each browser handles it slightly differently. Firefox skips back two pages in the history with new content and no error, and chrome skips back one, and displays the previous content (with error).
18
+
19
+ In a secure application, browsers are unable to determine the content from the internal cache and raise an error. Example from Chrome when clicking back button after successful redirect raises an `ERR_CACHE_MISS`:
20
+
21
+ ![Example of Chrome ERR_CACHE_MISS](https://f.cloud.github.com/assets/19973/2430174/318aa678-acc0-11e3-9bf8-0535d51a2fac.png)
22
+
23
+ For full protection from ERR_CACHE_MISS, and equivalent in other browsers, the pattern should be altered to follow a full POST-REDIRECT-GET patten.
24
+
25
+ Full Post-Redirect-Get pattern:
26
+ * POST form
27
+ * Error generated -> ***redirect*** back displaying errors
28
+ * POST form
29
+ * No errors -> Redirect to successful action
30
+
31
+ This way the browser will always have a consistent back-button history to traverse without
32
+ triggering browser errors. This error can also be triggered by:
33
+ * Browser crashing (and attempting restore)
34
+ * Abnormal closure of browser such as power cutting out (and attempting restore)
35
+ * 'Restore' last session
4
36
 
5
37
  ## Installation
6
38
 
@@ -18,27 +50,145 @@ Or install it yourself as:
18
50
 
19
51
  ## Usage
20
52
 
21
- TODO: Write usage instructions here
53
+ The standard controller method for Rails (in a changing action like Create/Update) would look like:
54
+
55
+ ```
56
+ def update
57
+ if @object.save
58
+ flash[:notice] = 'Huzzah - I was successful!'
59
+ redirect_to objects_path
60
+ else
61
+ flash[:error] = 'Oh no - saving failed'
62
+
63
+ render :edit
64
+ end
65
+ end
66
+ ```
67
+
68
+ To enable full Post-Redirect-Get for errors, the object has to be reinitialized after the redirect with both the set params and the new errors via the flash object (one request only). For security reasons, this will raise errors unless `permitted` params are passed for the redirect (see [strong parameters](http://api.rubyonrails.org/classes/ActionController/Parameters.html)).
69
+
70
+ Using `Rails-Prg` and to implement full POST-REDIRECT-GET this action (and any other change action such as `create`) should be changed to the following.
71
+
72
+ Example with filters:
73
+
74
+ ```
75
+ before_filter :load_object, only: [:edit, :update]
76
+ before_filter :load_redirected_objects!, only: [:edit]
77
+
78
+ def update
79
+ if @object.save
80
+ flash[:notice] = 'Huzzah - I was successful!'
81
+ redirect_to objects_path
82
+ else
83
+ set_redirected_object!('@object', @object, clean_params) # Pass errors
84
+ redirect_to edit_object_path(@object) # Redirect back
85
+ end
86
+ end
87
+ ```
88
+
89
+ On redirection to the edit page the filter `set_redirected_object!` will assign any params passed on to the object (by submission) and any errors present in the flash object to act as normal, as if it was simply rendered on the previous page.
90
+
91
+ Example without filters:
92
+
93
+ ```
94
+ def new
95
+ @object = Object.new
96
+ load_redirected_objects!
97
+ end
98
+
99
+ def create
100
+ @object = Object.new(params[:object])
101
+
102
+ if @object.save
103
+ flash[:notice] = 'Huzzah - I was created!'
104
+ redirect_to objects_path
105
+ else
106
+ set_redirected_object!('@object', @object, safe_params) # Pass errors
107
+ redirect_to new_object_path # Redirect back
108
+ end
109
+ end
110
+ ```
111
+
112
+ This strategy also has the benefit of being completely uniform across all browsers in behaviour. Before, for instance, Chrome ended on a different page to Firefox when clicking back (one skips a page in history and goes further back, chrome displays with the errors instead).
113
+
114
+
115
+ ## Further explanation
116
+
117
+ The way Rails `render`s an error instead of redirecting, is completely expected and normal. The primary reason is for performance, no additional HTTP hit required, and the object is already loaded (with errors). Pretty much every framework has a similar strategy. In fact, you can duplicate the browser cache bug in the majority of secure websites online today.
118
+
119
+ However, though better for performance reasons, this breaks the old browser pattern of POST-REDIRECT-GET (http://en.wikipedia.org/wiki/Post/Redirect/Get)
120
+
121
+ ```
122
+ Post/Redirect/Get (PRG) is a web development design pattern that prevents some duplicate form
123
+ submissions, creating a more intuitive interface for user agents (users). PRG implements
124
+ bookmarks and the refresh button in a predictable way that does not create duplicate
125
+ form submissions.
126
+ ```
127
+
128
+ ![POST REDIRECT GET example](http://upload.wikimedia.org/wikipedia/commons/3/3c/PostRedirectGet_DoubleSubmitSolution.png)
129
+
130
+ As such, for a secure application, we need to always ensure `no-cache,no-store` is set, and always use the POST-REDIRECT-GET pattern.
131
+
132
+ ### Browser peculiarities
133
+
134
+ Chrome (other browsers have their own equivalent) has the following code that breaks with the Rails method when `no-store` is set:
135
+ * https://chromium.googlesource.com/chromium/chromium/+/master/webkit/appcache/appcache_response.cc
136
+
137
+ Chrome code:
138
+ ```
139
+ void AppCacheResponseReader::ContinueReadData() {
140
+ if (!entry_) {
141
+ ScheduleIOCompletionCallback(net::ERR_CACHE_MISS);
142
+ return;
143
+ }
144
+ }
145
+ ```
146
+
147
+ Basically, with `no-store` as a header, and allowing 'back button' to be used, the browser gets into a state, where it attempts to load the rendered error page (without redirect) and the headers have already blocked saving the history, and raises the `ERR_CACHE_MISS` error.
148
+
149
+ With POST-REDIRECT-GET pattern this is avoided (as the form submission page always ends in redirect)
150
+
151
+ Example of error displayed on Chrome:
152
+
153
+ ![Example of Chrome ERR_CACHE_MISS Process](https://f.cloud.github.com/assets/19973/2430175/4117352a-acc0-11e3-9deb-ba209fa49097.gif)
22
154
 
23
155
  ## Contributing
24
156
 
25
- 1. Fork it ( http://github.com/<my-github-username>/rails-prg/fork )
157
+ 1. Fork it ( http://github.com/tommeier/rails-prg/fork )
26
158
  2. Create your feature branch (`git checkout -b my-new-feature`)
159
+ 3. Add specs and ensure all tests pass (in multiple browsers)
27
160
  3. Commit your changes (`git commit -am 'Add some feature'`)
28
161
  4. Push to the branch (`git push origin my-new-feature`)
29
162
  5. Create new Pull Request
30
163
 
164
+ ## Running tests
31
165
 
32
- ## Note how to generate dummy rails app
166
+ To display in Chrome browsers, ensure you have the latest `chromedriver` installed:
33
167
 
34
- * Command for dummy rails app
35
- * Scaffolding request objects:
36
- * `rails generate scaffold ExamplePrg subject:text:uniq body:text published:boolean`
37
- * `rails generate scaffold ErrorDuplicator subject:text:uniq body:text published:boolean`
168
+ `brew install chromedriver`
38
169
 
39
- ## TODO
40
- * Write up README
41
- * Add steps to install chromedriver to readme
170
+ ### Running all tests, with setup, Chrome and Firefox browser features
171
+
172
+ `script/spec`
173
+
174
+ ### Running features only in Chrome
175
+
176
+ `BROWSER=chrome rspec spec/rails/prg/features`
177
+
178
+ ### Running features only in Firefox (default)
179
+
180
+ `BROWSER=firefox rspec spec/rails/prg/features`
181
+
182
+ ## Appendix
183
+
184
+ ### TODO
42
185
  * When Open sourced:
43
186
  * Add Travis-CI
44
187
  * use sauce labs 'Open Sauce' to check in multiple browsers for result and remove 'selenium_display' (or only enable for manual local run, run script/ci for travis, script/spec for local)
188
+
189
+ ### How to to generate dummy rails app for test structure (use when updating rails)
190
+
191
+ * Command for dummy rails app
192
+ * Scaffolding request objects:
193
+ * `rails generate scaffold ExamplePrg subject:text:uniq body:text published:boolean`
194
+ * `rails generate scaffold ErrorDuplicator subject:text:uniq body:text published:boolean`
@@ -1,5 +1,5 @@
1
1
  module Rails
2
2
  module Prg
3
- VERSION = "0.1.0"
3
+ VERSION = "0.1.1"
4
4
  end
5
5
  end
@@ -10,13 +10,16 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["tom@venombytes.com"]
11
11
  spec.summary = %q{Allow Rails to use full POST-REDIRECT-GET pattern on errors.}
12
12
  spec.description = %q{
13
- Secure applications must not use browser history or cache, this can cause problems
14
- with some browsers when following standard Rails pattern for POST -> Error -> Render -> Success -> Redirect.
15
- For full protection from ERR_CACHE_MISS (in Chrome with no-cache, no-store),
16
- Rails should redirect on errors as well as on success,
17
- always following full POST-REDIRECT-GET pattern.
18
- This way the browser will always have a consistent back-button history to traverse without
19
- triggering browser errors unable to display form submission pages.
13
+ Secure applications disable browser history and internal cache.
14
+ Unfortunately, this causes problems with most browsers when following
15
+ the standard Rails pattern for displaying errors.
16
+
17
+ For full protection from ERR_CACHE_MISS (in Chrome with no-cache, no-store),
18
+ and equivalent in other browsers, the pattern should be altered to follow
19
+ a full POST-REDIRECT-GET patten.
20
+
21
+ This way the browser will always have a consistent back-button history to
22
+ traverse without triggering browser errors.
20
23
  }
21
24
  spec.homepage = "https://github.com/tommeier/rails-prg"
22
25
  spec.license = "MIT"
@@ -36,6 +39,8 @@ Gem::Specification.new do |spec|
36
39
  spec.add_development_dependency "database_cleaner"
37
40
  spec.add_development_dependency "rake"
38
41
  spec.add_development_dependency "rspec-rails"
42
+ spec.add_development_dependency "sauce", "~> 3.1.1"
43
+ spec.add_development_dependency "sauce-connect"
39
44
  spec.add_development_dependency "selenium-webdriver"
40
45
  spec.add_development_dependency "simplecov"
41
46
  spec.add_development_dependency "sqlite3"
@@ -1,4 +1,4 @@
1
- #!/bin/sh -xe
1
+ #!/bin/bash -xe
2
2
 
3
3
  # Install packages.
4
4
  bundle --quiet --binstubs
@@ -19,4 +19,10 @@ export CHECK_SPEC_COVERAGE=${CHECK_SPEC_COVERAGE:-false}
19
19
  COVERAGE_GROUP="unit-tests" bin/rake "spec:unit"
20
20
  COVERAGE_GROUP="firefox-features" BROWSER=firefox bin/rake "spec:features"
21
21
  COVERAGE_GROUP="chrome-features" BROWSER=chrome bin/rake "spec:features"
22
+
23
+ if [ ! -z "$USE_SAUCE" ]; then
24
+ COVERAGE_GROUP="safari-features" BROWSER=safari bin/rake "spec:features"
25
+ COVERAGE_GROUP="ie8-features" BROWSER=ie8 bin/rake "spec:features"
26
+ fi
27
+
22
28
  bin/rake "spec:quality"
@@ -7,7 +7,6 @@
7
7
  <%= csrf_meta_tags %>
8
8
  </head>
9
9
  <body>
10
-
11
10
  <%= yield %>
12
11
 
13
12
  </body>
@@ -47,8 +47,15 @@ feature "Standard Rails render on errors" do
47
47
  click_button "More" #triggers chrome to load error code
48
48
  expect(page.find("div.error-code")).to have_text("Error code: ERR_CACHE_MISS")
49
49
  end
50
+ when :safari
51
+ #Unable to duplicate except visually
52
+ # safariDriver cannot handle alerts, or be aware of them
53
+ # Behaviour: Safari shows 'confirm form resubmission' alert box
54
+ when :"Internet Explorer"
55
+ # IE 8
56
+ expect(page.body).to have_text("The local copy of this webpage is out of date, and the website requires that you download it again.")
50
57
  else
51
- raise "Error - Unhandled browser"
58
+ raise "Error - Unhandled browser: #{$selenium_display.browser.to_sym}"
52
59
  end
53
60
  end
54
61
 
@@ -87,14 +94,23 @@ feature "Standard Rails render on errors" do
87
94
  page.should have_content("Editing error_duplicator")
88
95
  expect(page).to_not have_text("Subject can't be blank")
89
96
  expect(page).to have_field('Subject', with: "") #Posted value
90
- when :chrome
97
+ when :chrome, :safari
91
98
  # Backs all the way back to show page with errors (post -> rendered error)
92
99
  expect(page.current_path).to eq(error_duplicator_path(existing_example))
93
100
  page.should have_content("Editing error_duplicator")
94
101
  expect(page).to have_text("Subject can't be blank")
95
102
  expect(page).to have_field('Subject', with: "updated test input") #updated value
103
+ when :"Internet Explorer"
104
+ # Occasionally IE8 barfs with this error page in Sauce. Ignore.
105
+ unless page.current_path == "/repost.htm"
106
+ # Backs all the way back to edit page without errors but content filled
107
+ expect(page.current_path).to eq(edit_error_duplicator_path(existing_example))
108
+ page.should have_content("Editing error_duplicator")
109
+ expect(page).to_not have_text("Subject can't be blank")
110
+ expect(page).to have_field('Subject', with: "updated test input") #Posted value
111
+ end
96
112
  else
97
- raise "Error - Unhandled browser"
113
+ raise "Error - Unhandled browser: #{$selenium_display.browser.to_sym}"
98
114
  end
99
115
  end
100
116
  end
@@ -41,14 +41,14 @@ feature "Use full post-redirect-get displaying original params and errors on red
41
41
 
42
42
  # Browser specific redirection
43
43
  case $selenium_display.browser.to_sym
44
- when :firefox
44
+ when :firefox, :"Internet Explorer"
45
45
  # Backs to the new page being completely empty
46
46
  expect(page).to have_field('Subject', with: "")
47
- when :chrome
47
+ when :chrome, :safari
48
48
  # Backs to the new page with original entries already loaded
49
49
  expect(page).to have_field('Subject', with: "testing NEW input")
50
50
  else
51
- raise "Error - Unhandled browser"
51
+ raise "Error - Unhandled browser: #{$selenium_display.browser.to_sym}"
52
52
  end
53
53
  end
54
54
 
@@ -83,10 +83,18 @@ feature "Use full post-redirect-get displaying original params and errors on red
83
83
  # On click of back button
84
84
  page.execute_script("window.history.back();")
85
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)
86
+ # Browser specific redirection
87
+ case $selenium_display.browser.to_sym
88
+ when :"Internet Explorer"
89
+ # IE8 is unstable, sometimes skips back to 'show' or to 'edit' or sometimes nothing at all
90
+ # expect(page.current_path).to eq(example_prg_path(existing_example))
91
+ # expect(page).not_to have_text("Subject can't be blank")
92
+ else
93
+ # Should have redirected back to edit page with errors
94
+ expect(page.current_path).to eq(edit_example_prg_path(existing_example))
95
+ expect(page).to have_text("Subject can't be blank")
96
+ expect(page).to have_field('Subject', with: "updated test input")
97
+ expect(page).to have_field('Published', with: 1)
98
+ end
91
99
  end
92
100
  end
@@ -1,4 +1,7 @@
1
- require 'selenium-webdriver'
1
+ require "selenium/webdriver"
2
+ require 'selenium/webdriver/remote/http/persistent'
3
+ require "sauce/config"
4
+ require "sauce/connect"
2
5
 
3
6
  Device = Struct.new(:width, :height)
4
7
 
@@ -19,11 +22,22 @@ class SeleniumDisplay
19
22
  self.device_name = ENV['DEVICE'] || 'desktop'
20
23
  self.device = define_device(device_name)
21
24
 
25
+ set_travis_options! if running_on_travis?
26
+ set_sauce_options! if use_sauce?
27
+
22
28
  print_debug_info if ENV['SELENIUM_DEBUG']
23
29
  end
24
30
 
25
31
  private
26
32
 
33
+ def running_on_travis?
34
+ !ENV['TRAVIS_JOB_NUMBER'].nil?
35
+ end
36
+
37
+ def use_sauce?
38
+ !ENV['USE_SAUCE'].nil?
39
+ end
40
+
27
41
  def define_device device_type
28
42
  case device_type.strip.downcase
29
43
  when 'phone'
@@ -42,18 +56,23 @@ class SeleniumDisplay
42
56
  def define_browser_capability
43
57
  case browser
44
58
  when /ie\d+/
45
- self.browser_capability = Selenium::WebDriver::Remote::Capabilities.ie
46
- self.browser_capability.version = (browser.match /ie(?<version>\d+)/)[:version]
47
- self.browser_capability.platform = "windows"
48
- self.browser = 'ie'
59
+ self.browser_capability = Selenium::WebDriver::Remote::Capabilities.internet_explorer
60
+ version_number = (browser.match /ie(?<version>\d+)/)[:version]
61
+
62
+ self.browser_capability.platform = version_number.to_i <= 8 ? "Windows XP" : "Windows 7"
63
+ self.browser_capability.version = version_number
64
+ self.browser = 'Internet Explorer'
49
65
  when 'chrome'
50
66
  self.browser_capability = Selenium::WebDriver::Remote::Capabilities.chrome
51
-
52
67
  when 'ipad'
53
68
  self.browser_capability = Selenium::WebDriver::Remote::Capabilities.ipad
54
69
  self.resizable = false
55
70
  when 'iphone'
56
71
  self.browser_capability = Selenium::WebDriver::Remote::Capabilities.iphone
72
+ self.browser_capability.platform = "OS X 10.9" #Sauce labs
73
+ self.browser_capability.version = "7"
74
+ self.browser_capability['device-orientation'] = 'portrait'
75
+
57
76
  self.resizable = false
58
77
  when 'firefox'
59
78
  self.browser_capability = Selenium::WebDriver::Remote::Capabilities.firefox
@@ -62,12 +81,99 @@ class SeleniumDisplay
62
81
  profile['extensions.update.enabled'] = false
63
82
  profile['app.update.auto'] = false
64
83
  profile['app.update.enabled'] = false
65
- self.selenium_options.merge!({:profile => profile })
84
+ self.selenium_options.merge!(profile: profile)
85
+ when 'android'
86
+ self.browser_capability = Selenium::WebDriver::Remote::Capabilities.android
87
+ when 'safari'
88
+ # Sauce labs
89
+ self.browser_capability = Selenium::WebDriver::Remote::Capabilities.safari
90
+ self.browser_capability.platform = "OS X 10.9"
91
+ self.browser_capability.version = "7"
66
92
  else
67
93
  raise "Error - Unsupported browser format '#{browser}'"
68
94
  end
69
95
  end
70
96
 
97
+ def set_travis_options!
98
+ self.browser_capability["build"] = ENV["TRAVIS_BUILD_NUMBER"]
99
+ end
100
+
101
+ def set_sauce_options!
102
+ raise_on_missing_sauce_variables! unless running_on_travis?
103
+
104
+ sauce_config = Sauce::Config.new
105
+ host = sauce_config[:application_host] || "127.0.0.1"
106
+ port = sauce_config[:application_port]
107
+
108
+ Capybara.server_port = port
109
+ Capybara.app_host = "http://#{host}:#{port}"
110
+ Capybara.default_wait_time = 30
111
+
112
+ client = ::Selenium::WebDriver::Remote::Http::Persistent.new
113
+ client.timeout = 300
114
+
115
+ if running_on_travis?
116
+ # Running on Travis CI (use existing tunnel)
117
+ self.browser_capability["tunnel-identifier"] = ENV["TRAVIS_JOB_NUMBER"]
118
+ else
119
+ # Connect local tunnel (and wait for connection)
120
+ Sauce::Connect.connect!
121
+ end
122
+
123
+ self.selenium_options.delete(:profile) #Incompatible
124
+
125
+ url = "http://#{sauce_config.username}:#{sauce_config.access_key}@#{sauce_config.host}:#{sauce_config.port}/wd/hub"
126
+ #client_version => Unnecessary, chooses latest
127
+ #platform => allow browser capability to set (default: linux)
128
+ self.browser_capability.merge!(
129
+ name: sauce_job_name,
130
+ browserName: browser
131
+ )
132
+ self.selenium_options.merge!(
133
+ browser: :remote,
134
+ url: url,
135
+ desired_capabilities: self.browser_capability,
136
+ http_client: client
137
+ )
138
+
139
+ set_build_to_notify_sauce!
140
+ end
141
+
142
+ def sauce_job_name
143
+ [ENV['TRAVIS_JOB_NUMBER'], browser, device_name].compact.join(" : ")
144
+ end
145
+
146
+ def raise_on_missing_sauce_variables!
147
+ # Required sauce variables
148
+ %w( SAUCE_USERNAME SAUCE_ACCESS_KEY ).each do |env_var|
149
+ raise "Error - set #{env_var} for access to open-sauce for selenium tests" unless ENV[env_var]
150
+ end
151
+ end
152
+
153
+ def set_build_to_notify_sauce!
154
+ # Notify sauce labs of build result if any specs were:
155
+ # * JS related (browser specs)
156
+ RSpec.configure do |config|
157
+ config.prepend_after(:suite) do
158
+ examples = RSpec.world.filtered_examples.values.flatten
159
+ sauce_results = examples.inject({ passed: [], failed: [], total: 0 }) do |result, example|
160
+ if example.metadata[:js] #only js features
161
+ result[:total] += 1
162
+ result[example.metadata[:execution_result][:status].to_sym] << example
163
+ end
164
+ result
165
+ end
166
+
167
+ if sauce_results[:total] && sauce_results[:total] > 0
168
+ job_result = sauce_results[:failed].count > 0 ? "failed" : "passed"
169
+ Capybara.using_driver(:selenium_browser) do
170
+ Capybara.current_session.driver.execute_script("sauce:job-result=#{job_result}")
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
176
+
71
177
  def print_debug_info
72
178
  STDERR.puts " >> Loading Selenium display"
73
179
  STDERR.puts " ->> browser : #{browser}"
@@ -1,3 +1,4 @@
1
+ # Use selenium display
1
2
  require 'support/selenium_display'
2
3
  require 'capybara'
3
4
 
@@ -10,7 +10,7 @@ class SimpleCov::Formatter::QualityFormatter
10
10
  end
11
11
  end
12
12
 
13
- SimpleCov.merge_timeout 240 #4 mins
13
+ SimpleCov.merge_timeout 1800 #30 mins
14
14
  if suite_name = ENV["COVERAGE_GROUP"]
15
15
  SimpleCov.command_name(suite_name)
16
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-prg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Meier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-16 00:00:00.000000000 Z
11
+ date: 2014-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -136,6 +136,34 @@ dependencies:
136
136
  - - '>='
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: sauce
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ~>
144
+ - !ruby/object:Gem::Version
145
+ version: 3.1.1
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ~>
151
+ - !ruby/object:Gem::Version
152
+ version: 3.1.1
153
+ - !ruby/object:Gem::Dependency
154
+ name: sauce-connect
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
139
167
  - !ruby/object:Gem::Dependency
140
168
  name: selenium-webdriver
141
169
  requirement: !ruby/object:Gem::Requirement
@@ -192,14 +220,13 @@ dependencies:
192
220
  - - '>='
193
221
  - !ruby/object:Gem::Version
194
222
  version: '0'
195
- description: "\n Secure applications must not use browser history or cache, this
196
- can cause problems\n with some browsers when following standard Rails pattern
197
- for POST -> Error -> Render -> Success -> Redirect.\n For full protection from
198
- ERR_CACHE_MISS (in Chrome with no-cache, no-store),\n Rails should redirect on
199
- errors as well as on success,\n always following full POST-REDIRECT-GET pattern.\n
200
- \ This way the browser will always have a consistent back-button history to traverse
201
- without\n triggering browser errors unable to display form submission pages.\n
202
- \ "
223
+ description: "\n Secure applications disable browser history and internal cache.\n
224
+ \ Unfortunately, this causes problems with most browsers when following\n the standard
225
+ Rails pattern for displaying errors.\n\n For full protection from ERR_CACHE_MISS
226
+ (in Chrome with no-cache, no-store),\n and equivalent in other browsers, the pattern
227
+ should be altered to follow\n a full POST-REDIRECT-GET patten.\n\n This way the
228
+ browser will always have a consistent back-button history to\n traverse without
229
+ triggering browser errors.\n "
203
230
  email:
204
231
  - tom@venombytes.com
205
232
  executables: []
@@ -209,6 +236,7 @@ files:
209
236
  - .cane
210
237
  - .gitignore
211
238
  - .rspec
239
+ - .travis.yml
212
240
  - Gemfile
213
241
  - LICENSE.txt
214
242
  - README.md