1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/actionpack/lib/action_dispatch/system_test_case.rb

197 lines
6.9 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
gem "capybara", ">= 3.26"
require "capybara/dsl"
require "capybara/minitest"
require "action_controller"
require "action_dispatch/system_testing/driver"
2018-01-15 14:21:48 -05:00
require "action_dispatch/system_testing/browser"
require "action_dispatch/system_testing/server"
require "action_dispatch/system_testing/test_helpers/screenshot_helper"
require "action_dispatch/system_testing/test_helpers/setup_and_teardown"
module ActionDispatch
# = System Testing
#
# System tests let you test applications in the browser. Because system
# tests use a real browser experience, you can test all of your JavaScript
# easily from your test suite.
#
# To create a system test in your application, extend your test class
# from <tt>ApplicationSystemTestCase</tt>. System tests use Capybara as a
# base and allow you to configure the settings through your
# <tt>application_system_test_case.rb</tt> file that is generated with a new
# application or scaffold.
#
# Here is an example system test:
#
# require "application_system_test_case"
#
# class Users::CreateTest < ApplicationSystemTestCase
# test "adding a new user" do
# visit users_path
# click_on 'New User'
#
# fill_in 'Name', with: 'Arya'
# click_on 'Create User'
#
# assert_text 'Arya'
# end
# end
#
# When generating an application or scaffold, an +application_system_test_case.rb+
# file will also be generated containing the base class for system testing.
# This is where you can change the driver, add Capybara settings, and other
# configuration for your system tests.
#
# require "test_helper"
#
# class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
# driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
# end
#
# By default, <tt>ActionDispatch::SystemTestCase</tt> is driven by the
# Selenium driver, with the Chrome browser, and a browser size of 1400x1400.
#
# Changing the driver configuration options is easy. Let's say you want to use
# the Firefox browser instead of Chrome. In your +application_system_test_case.rb+
# file add the following:
#
# require "test_helper"
#
# class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
# driven_by :selenium, using: :firefox
# end
#
# +driven_by+ has a required argument for the driver name. The keyword
# arguments are +:using+ for the browser and +:screen_size+ to change the
# size of the browser screen. These two options are not applicable for
# headless drivers and will be silently ignored if passed.
#
# Headless browsers such as headless Chrome and headless Firefox are also supported.
# You can use these browsers by setting the +:using+ argument to +:headless_chrome+ or +:headless_firefox+.
#
# To use a headless driver, like Cuprite, update your Gemfile to use
# Cuprite instead of Selenium and then declare the driver name in the
2017-06-06 11:31:24 -04:00
# +application_system_test_case.rb+ file. In this case, you would leave out
# the +:using+ option because the driver is headless, but you can still use
# +:screen_size+ to change the size of the browser screen, also you can use
# +:options+ to pass options supported by the driver. Please refer to your
# driver documentation to learn about supported options.
#
# require "test_helper"
# require "capybara/cuprite"
#
# class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
# driven_by :cuprite, screen_size: [1400, 1400], options:
2017-06-06 11:31:24 -04:00
# { js_errors: true }
# end
#
# Some drivers require browser capabilities to be passed as a block instead
# of through the +options+ hash.
#
# 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 with a block.
#
# The block will be passed an instance of <tt><Driver>::Options</tt> where you can
# define the capabilities you want. Please refer to your driver documentation
# to learn about supported options.
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 ```
2018-04-03 21:58:39 -04:00
#
# class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
# driven_by :selenium, using: :chrome, screen_size: [1024, 768] do |driver_option|
# driver_option.add_emulation(device_name: 'iPhone 6')
# driver_option.add_extension('path/to/chrome_extension.crx')
# end
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 ```
2018-04-03 21:58:39 -04:00
# 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.
class SystemTestCase < ActiveSupport::TestCase
include Capybara::DSL
include Capybara::Minitest::Assertions
include SystemTesting::TestHelpers::SetupAndTeardown
include SystemTesting::TestHelpers::ScreenshotHelper
DEFAULT_HOST = "http://127.0.0.1"
def initialize(*) # :nodoc:
super
self.class.driven_by(:selenium) unless self.class.driver?
self.class.driver.use
end
def self.start_application # :nodoc:
Capybara.app = Rack::Builder.new do
map "/" do
run Rails.application
end
end
SystemTesting::Server.new.run
end
class_attribute :driver, instance_accessor: false
# System Test configuration options
#
# The default settings are Selenium, using Chrome, with a screen size
# of 1400x1400.
#
# Examples:
#
# driven_by :cuprite
#
# driven_by :selenium, screen_size: [800, 800]
#
# driven_by :selenium, using: :chrome
#
# driven_by :selenium, using: :headless_chrome
#
# driven_by :selenium, using: :firefox
#
# driven_by :selenium, using: :headless_firefox
def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {}, &capabilities)
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 ```
2018-04-03 21:58:39 -04:00
driver_options = { using: using, screen_size: screen_size, options: options }
self.driver = SystemTesting::Driver.new(driver, **driver_options, &capabilities)
end
private
def url_helpers
@url_helpers ||=
if ActionDispatch.test_app
Class.new do
include ActionDispatch.test_app.routes.url_helpers
include ActionDispatch.test_app.routes.mounted_helpers
def url_options
default_url_options.reverse_merge(host: app_host)
end
def app_host
Capybara.app_host || Capybara.current_session.server_url || DEFAULT_HOST
end
end.new
end
end
def method_missing(name, *args, &block)
if url_helpers.respond_to?(name)
url_helpers.public_send(name, *args, &block)
else
super
end
end
def respond_to_missing?(name, include_private = false)
url_helpers.respond_to?(name)
end
end
end
ActiveSupport.run_load_hooks :action_dispatch_system_test_case, ActionDispatch::SystemTestCase
ActionDispatch::SystemTestCase.start_application