aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdouard CHIN <edouard.chin@shopify.com>2018-04-03 21:58:39 -0400
committerEileen Uchitelle <eileencodes@gmail.com>2019-01-29 08:50:29 -0500
commit01a26e581f977b08de072ce3c40b9adee2ba1c10 (patch)
treec30654236e9443a056f3990a42577412411a0627
parent2f9f699a2f6c6d470d2c639fe07d7850f6858c53 (diff)
downloadrails-01a26e581f977b08de072ce3c40b9adee2ba1c10.tar.gz
rails-01a26e581f977b08de072ce3c40b9adee2ba1c10.tar.bz2
rails-01a26e581f977b08de072ce3c40b9adee2ba1c10.zip
Implement a way to add browser capabilities:
* There is currently no way to define specific browser capabilities since our SystemTest driver override the `option` key [Ref](https://github.com/rails/rails/blob/a07d0680787ced3c04b362fa7a238c918211ac70/actionpack/lib/action_dispatch/system_testing/driver.rb#L35) This option key is used internally by selenium to add custom capabilities on the browser. Depending on the Browser, some option are allowed to be passed inside a hash, the driver takes care of setting whatever you passed on the driver option. An example [here](https://github.com/rails/rails/blob/a07d0680787ced3c04b362fa7a238c918211ac70/actionpack/lib/action_dispatch/system_testing/driver.rb#L35) where you are allowed to pass args such as `--no-sandbox` etc However this behavior was only meant for backward compatibility and as you can see it's deprecated. The non-deprecated behavior is to create a `<Driver>::Option` object containing all the capabilities we want. This is what we [currently do](https://github.com/rails/rails/blob/a07d0680787ced3c04b362fa7a238c918211ac70/actionpack/lib/action_dispatch/system_testing/browser.rb#L34-L36) when chrome or firefox are in headless mode. This PR allows to pass a block when calling `driven_by`, the block will be pased a `<Driver>::Option` instance. You can modify this object the way you want by adding any capabilities. The option object will be then passed to selenium. ```ruby driven_by :selenium, using: :chrome do |driver_option| driver_option.add_argument('--no-sandbox') driver_option.add_emulation(device: 'iphone 4') end ```
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock1
-rw-r--r--actionpack/CHANGELOG.md7
-rw-r--r--actionpack/lib/action_dispatch/system_test_case.rb20
-rw-r--r--actionpack/lib/action_dispatch/system_testing/browser.rb21
-rw-r--r--actionpack/lib/action_dispatch/system_testing/driver.rb9
-rw-r--r--actionpack/test/dispatch/system_testing/driver_test.rb67
-rw-r--r--railties/test/application/test_runner_test.rb2
8 files changed, 117 insertions, 11 deletions
diff --git a/Gemfile b/Gemfile
index 92f45d9f58..6914d9baab 100644
--- a/Gemfile
+++ b/Gemfile
@@ -10,6 +10,7 @@ gemspec
gem "rake", ">= 11.1"
gem "capybara", ">= 2.15"
+gem "selenium-webdriver", "~> 3.5.1"
gem "rack-cache", "~> 1.2"
gem "sass-rails"
diff --git a/Gemfile.lock b/Gemfile.lock
index 1f02b9c4c7..62be590ffb 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -568,6 +568,7 @@ DEPENDENCIES
rubocop (>= 0.47)
sass-rails
sdoc (~> 1.0)
+ selenium-webdriver (~> 3.5.1)
sequel
sidekiq
sneakers
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 1d2f6b09c3..024e03ad7a 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,8 @@
+* `ActionDispatch::SystemTestCase.driven_by` can now be called with a block to define specific browser capabilities.
+
+ *Edouard Chin*
+
+
## Rails 6.0.0.beta1 (January 18, 2019) ##
* Remove deprecated `fragment_cache_key` helper in favor of `combined_fragment_cache_key`.
@@ -154,7 +159,7 @@
*Aaron Kromer*
-* Pass along arguments to underlying `get` method in `follow_redirect!`.
+* Pass along arguments to underlying `get` method in `follow_redirect!`
Now all arguments passed to `follow_redirect!` are passed to the underlying
`get` method. This for example allows to set custom headers for the
diff --git a/actionpack/lib/action_dispatch/system_test_case.rb b/actionpack/lib/action_dispatch/system_test_case.rb
index c74c0ccced..644c703dc9 100644
--- a/actionpack/lib/action_dispatch/system_test_case.rb
+++ b/actionpack/lib/action_dispatch/system_test_case.rb
@@ -89,6 +89,20 @@ module ActionDispatch
# { js_errors: true }
# end
#
+ # Most drivers won't let you add specific browser capabilities through the +options+ mentioned above.
+ # As an example, if you want to add mobile emulation on chrome, you'll have to create an instance of selenium's
+ # `Chrome::Options` object and add capabilities to it.
+ # To make things easier, `driven_by` can be called with a block.
+ # The block will be passed an instance of `<Driver>::Options` where you can define the capabilities you want.
+ # Please refer to your driver documentation to learn about supported options.
+ #
+ # class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
+ # driven_by :chrome, screen_size: [1024, 768] do |driver_option|
+ # driver_option.add_emulation(device: 'iPhone 6')
+ # driver_option.add_extension('path/to/chrome_extension.crx')
+ # end
+ # end
+ #
# Because <tt>ActionDispatch::SystemTestCase</tt> is a shim between Capybara
# and Rails, any driver that is supported by Capybara is supported by system
# tests as long as you include the required gems and files.
@@ -134,8 +148,10 @@ module ActionDispatch
# driven_by :selenium, using: :firefox
#
# driven_by :selenium, using: :headless_firefox
- def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {})
- self.driver = SystemTesting::Driver.new(driver, using: using, screen_size: screen_size, options: options)
+ def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {}, &desired_capabilities)
+ driver_options = { using: using, screen_size: screen_size, options: options }
+
+ self.driver = SystemTesting::Driver.new(driver, driver_options, &desired_capabilities)
end
driven_by :selenium
diff --git a/actionpack/lib/action_dispatch/system_testing/browser.rb b/actionpack/lib/action_dispatch/system_testing/browser.rb
index 1b0bce6b9e..9361b165ff 100644
--- a/actionpack/lib/action_dispatch/system_testing/browser.rb
+++ b/actionpack/lib/action_dispatch/system_testing/browser.rb
@@ -29,20 +29,27 @@ module ActionDispatch
end
end
+ def driver_option
+ @option ||= case type
+ when :chrome
+ Selenium::WebDriver::Chrome::Options.new
+ when :firefox
+ Selenium::WebDriver::Firefox::Options.new
+ end
+ end
+
private
def headless_chrome_browser_options
- options = Selenium::WebDriver::Chrome::Options.new
- options.args << "--headless"
- options.args << "--disable-gpu" if Gem.win_platform?
+ driver_option.args << "--headless"
+ driver_option.args << "--disable-gpu" if Gem.win_platform?
- options
+ driver_option
end
def headless_firefox_browser_options
- options = Selenium::WebDriver::Firefox::Options.new
- options.args << "-headless"
+ driver_option.args << "-headless"
- options
+ driver_option
end
end
end
diff --git a/actionpack/lib/action_dispatch/system_testing/driver.rb b/actionpack/lib/action_dispatch/system_testing/driver.rb
index 5252ff6746..87b72a2048 100644
--- a/actionpack/lib/action_dispatch/system_testing/driver.rb
+++ b/actionpack/lib/action_dispatch/system_testing/driver.rb
@@ -3,11 +3,12 @@
module ActionDispatch
module SystemTesting
class Driver # :nodoc:
- def initialize(name, **options)
+ def initialize(name, **options, &desired_capabilities)
@name = name
@browser = Browser.new(options[:using])
@screen_size = options[:screen_size]
@options = options[:options]
+ @desired_capabilities = desired_capabilities
end
def use
@@ -22,6 +23,8 @@ module ActionDispatch
end
def register
+ define_browser_capabilities(@browser.driver_option)
+
Capybara.register_driver @name do |app|
case @name
when :selenium then register_selenium(app)
@@ -31,6 +34,10 @@ module ActionDispatch
end
end
+ def define_browser_capabilities(driver_option)
+ @desired_capabilities.call(driver_option) if @desired_capabilities
+ end
+
def browser_options
@options.merge(options: @browser.options).compact
end
diff --git a/actionpack/test/dispatch/system_testing/driver_test.rb b/actionpack/test/dispatch/system_testing/driver_test.rb
index a824ee0c84..2ab8fac666 100644
--- a/actionpack/test/dispatch/system_testing/driver_test.rb
+++ b/actionpack/test/dispatch/system_testing/driver_test.rb
@@ -2,6 +2,7 @@
require "abstract_unit"
require "action_dispatch/system_testing/driver"
+require "selenium/webdriver"
class DriverTest < ActiveSupport::TestCase
test "initializing the driver" do
@@ -51,4 +52,70 @@ class DriverTest < ActiveSupport::TestCase
test "registerable? returns false if driver is rack_test" do
assert_not ActionDispatch::SystemTesting::Driver.new(:rack_test).send(:registerable?)
end
+
+ test "define extra capabilities using chrome" do
+ driver_option = nil
+ driver = ActionDispatch::SystemTesting::Driver.new(:selenium, screen_size: [1400, 1400], using: :chrome) do |option|
+ option.add_argument("start-maximized")
+ option.add_emulation(device_name: "iphone 6")
+ option.add_preference(:detach, true)
+
+ driver_option = option
+ end
+ driver.use
+
+ expected = { args: ["start-maximized"], mobileEmulation: { deviceName: "iphone 6" }, prefs: { detach: true } }
+ assert_equal expected, driver_option.as_json
+ end
+
+ test "define extra capabilities using headless_chrome" do
+ driver_option = nil
+ driver = ActionDispatch::SystemTesting::Driver.new(:selenium, screen_size: [1400, 1400], using: :headless_chrome) do |option|
+ option.add_argument("start-maximized")
+ option.add_emulation(device_name: "iphone 6")
+ option.add_preference(:detach, true)
+
+ driver_option = option
+ end
+ driver.use
+
+ expected = { args: ["start-maximized"], mobileEmulation: { deviceName: "iphone 6" }, prefs: { detach: true } }
+ assert_equal expected, driver_option.as_json
+ end
+
+ test "define extra capabilities using firefox" do
+ driver_option = nil
+ driver = ActionDispatch::SystemTesting::Driver.new(:selenium, screen_size: [1400, 1400], using: :firefox) do |option|
+ option.add_preference("browser.startup.homepage", "http://www.seleniumhq.com/")
+ option.add_argument("--host=127.0.0.1")
+
+ driver_option = option
+ end
+ driver.use
+
+ expected = { "moz:firefoxOptions" => { args: ["--host=127.0.0.1"], prefs: { "browser.startup.homepage" => "http://www.seleniumhq.com/" } } }
+ assert_equal expected, driver_option.as_json
+ end
+
+ test "define extra capabilities using headless_firefox" do
+ driver_option = nil
+ driver = ActionDispatch::SystemTesting::Driver.new(:selenium, screen_size: [1400, 1400], using: :headless_firefox) do |option|
+ option.add_preference("browser.startup.homepage", "http://www.seleniumhq.com/")
+ option.add_argument("--host=127.0.0.1")
+
+ driver_option = option
+ end
+ driver.use
+
+ expected = { "moz:firefoxOptions" => { args: ["--host=127.0.0.1"], prefs: { "browser.startup.homepage" => "http://www.seleniumhq.com/" } } }
+ assert_equal expected, driver_option.as_json
+ end
+
+ test "does not define extra capabilities" do
+ driver = ActionDispatch::SystemTesting::Driver.new(:selenium, screen_size: [1400, 1400], using: :firefox)
+
+ assert_nothing_raised do
+ driver.use
+ end
+ end
end
diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb
index fda6df500d..954eb68445 100644
--- a/railties/test/application/test_runner_test.rb
+++ b/railties/test/application/test_runner_test.rb
@@ -742,6 +742,7 @@ module ApplicationTests
def test_reset_sessions_before_rollback_on_system_tests
app_file "test/system/reset_session_before_rollback_test.rb", <<-RUBY
require "application_system_test_case"
+ require "selenium/webdriver"
class ResetSessionBeforeRollbackTest < ApplicationSystemTestCase
def teardown_fixtures
@@ -826,6 +827,7 @@ module ApplicationTests
def test_system_tests_are_run_through_rake_test_when_given_in_TEST
app_file "test/system/dummy_test.rb", <<-RUBY
require "application_system_test_case"
+ require "selenium/webdriver"
class DummyTest < ApplicationSystemTestCase
test "something" do