From 5bf0aa6745db27c45c0778f9f6e9046f9ee9fb94 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Sun, 6 Nov 2016 18:55:15 -0500 Subject: Turn system testing into it's own gem and rename Renames `Rails::SystemTestCase` to `ActionSystemTest` and moves it to a gem under the Rails name. We need to name the class `ActionSystemTestCase` because the gem expects a module but tests themselves expect a class. Adds MIT-LICENSE, CHANGELOG, and README for the future. --- actionsystemtest/CHANGELOG.md | 3 + actionsystemtest/MIT-LICENSE | 20 ++++ actionsystemtest/README.md | 108 +++++++++++++++++++++ actionsystemtest/Rakefile | 32 ++++++ actionsystemtest/actionsystemtest.gemspec | 24 +++++ actionsystemtest/lib/action_system_test.rb | 59 +++++++++++ .../lib/action_system_test/driver_adapter.rb | 31 ++++++ .../lib/action_system_test/driver_adapters.rb | 46 +++++++++ .../driver_adapters/capybara_driver.rb | 83 ++++++++++++++++ .../driver_adapters/rails_selenium_driver.rb | 98 +++++++++++++++++++ .../driver_adapters/web_server.rb | 45 +++++++++ .../lib/action_system_test/gem_version.rb | 15 +++ actionsystemtest/lib/action_system_test/railtie.rb | 17 ++++ .../lib/action_system_test/test_helper.rb | 23 +++++ .../lib/action_system_test/test_helpers.rb | 9 ++ .../action_system_test/test_helpers/assertions.rb | 40 ++++++++ .../action_system_test/test_helpers/form_helper.rb | 58 +++++++++++ .../test_helpers/screenshot_helper.rb | 47 +++++++++ actionsystemtest/lib/action_system_test/version.rb | 8 ++ actionsystemtest/test/abstract_unit.rb | 13 +++ .../test/cases/capybara_driver_test.rb | 39 ++++++++ actionsystemtest/test/cases/driver_adapter_test.rb | 13 +++ .../test/cases/rails_selenium_driver_test.rb | 11 +++ .../test/cases/screenshot_helper_test.rb | 20 ++++ 24 files changed, 862 insertions(+) create mode 100644 actionsystemtest/CHANGELOG.md create mode 100644 actionsystemtest/MIT-LICENSE create mode 100644 actionsystemtest/README.md create mode 100644 actionsystemtest/Rakefile create mode 100644 actionsystemtest/actionsystemtest.gemspec create mode 100644 actionsystemtest/lib/action_system_test.rb create mode 100644 actionsystemtest/lib/action_system_test/driver_adapter.rb create mode 100644 actionsystemtest/lib/action_system_test/driver_adapters.rb create mode 100644 actionsystemtest/lib/action_system_test/driver_adapters/capybara_driver.rb create mode 100644 actionsystemtest/lib/action_system_test/driver_adapters/rails_selenium_driver.rb create mode 100644 actionsystemtest/lib/action_system_test/driver_adapters/web_server.rb create mode 100644 actionsystemtest/lib/action_system_test/gem_version.rb create mode 100644 actionsystemtest/lib/action_system_test/railtie.rb create mode 100644 actionsystemtest/lib/action_system_test/test_helper.rb create mode 100644 actionsystemtest/lib/action_system_test/test_helpers.rb create mode 100644 actionsystemtest/lib/action_system_test/test_helpers/assertions.rb create mode 100644 actionsystemtest/lib/action_system_test/test_helpers/form_helper.rb create mode 100644 actionsystemtest/lib/action_system_test/test_helpers/screenshot_helper.rb create mode 100644 actionsystemtest/lib/action_system_test/version.rb create mode 100644 actionsystemtest/test/abstract_unit.rb create mode 100644 actionsystemtest/test/cases/capybara_driver_test.rb create mode 100644 actionsystemtest/test/cases/driver_adapter_test.rb create mode 100644 actionsystemtest/test/cases/rails_selenium_driver_test.rb create mode 100644 actionsystemtest/test/cases/screenshot_helper_test.rb (limited to 'actionsystemtest') diff --git a/actionsystemtest/CHANGELOG.md b/actionsystemtest/CHANGELOG.md new file mode 100644 index 0000000000..3c7ea2c273 --- /dev/null +++ b/actionsystemtest/CHANGELOG.md @@ -0,0 +1,3 @@ +* Added to Rails! + + *Eileen M. Uchitelle* diff --git a/actionsystemtest/MIT-LICENSE b/actionsystemtest/MIT-LICENSE new file mode 100644 index 0000000000..7fddc6b222 --- /dev/null +++ b/actionsystemtest/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2017 David Heinemeier Hansson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/actionsystemtest/README.md b/actionsystemtest/README.md new file mode 100644 index 0000000000..3710b8dbd4 --- /dev/null +++ b/actionsystemtest/README.md @@ -0,0 +1,108 @@ +# Action System Test + +Action System Test adds Capybara integration to your Rails application for +acceptance testing. This allows you to test the entire user experience +of your application rather than just your controllers, or just your models. + +Action System Test provides all of the setup out of the box for you to use +Capybara with the Selenium Driver in your Rails application. Changing the +default configuration is simple, yet flexible. + +## Examples + +### Usage + +By default Rails provides applications with system testing through Capybara +and defaults to using the Selenium driver. The configuration set by Rails +means that when you generate an application system tests will work out of +the box, without you having to change any of the configuration requirements. + +Action System Test uses all the helpers from Capybara, but abstracts away the +setup required to get running. Below is an example Action System Test. + +```ruby +class UsersTest < ActionSystemTestCase + setup do + visit users_path + end + + test 'creating a new user' do + click_on 'New User' + + fill_in 'Name', with: 'Arya' + + click_on 'Create User' + + assert_text 'Arya' + end +end +``` + +First we visit the +users_path+. From there we are going to use Action System +Test to create a new user. The test will click on the "New User" button. Then +it will fill in the "Name" field with "Arya" and click on the "Create User" +button. Lastly, we assert that the text on the Users show page is what we +expected, which in this case is "Arya". + +For more helpers and how to write Capybara tests visit Capybara's README. + +### Configuration + +When generating a new application Rails will include the Capybara gem, the +Selenium gem, and a system_test_helper.rb file. The +system_test_helper.rb file is where you can change the desired +configuration if Rails doesn't work out of the box for you. + +The system_test_helper.rb file provides a home for all of your Capybara +and Action System Test configuration. + +Rails preset configuration for Capybara with Selenium defaults to Puma for +the web server on port 28100, Chrome for the browser, and a screen size of +1400 x 1400. + +Changing the configuration is as simple as changing the driver in your +system_test_helper.rb + +If you want to change the default settings of the Rails provided Selenium +configuration options you can initialize a new RailsSeleniumDriver +object. + +```ruby +class ActionSystemTestCase < ActionSystemTest::Base + ActionSystemTest.driver = RailsSeleniumDriver.new( + browser: :firefox, + server: :webrick + ) +end +``` + +Capybara itself provides 4 drivers: RackTest, Selenium, Webkit, and Poltergeist. +Action System Test provides a shim between Rails and Capybara for these 4 drivers. +Please note, that Rails is set up to use the Puma server by default for these +4 drivers. Puma is the default in Rails and therefore is set as the default in +the Rails Capybara integration. + +To set your application tests to use any of Capybara's defaults with no configuration, +set the following in your system_test_helper.rb file and follow setup instructions +for environment requirements of these drivers. + +The possible settings are +:rack_test+, +:selenium+, +:webkit+, or +:poltergeist+. + +```ruby +class ActionSystemTestCase < ActionSystemTest::Base + ActionSystemTest.driver = :poltergeist +end +``` + +If you want to change the default server (puma) or port (28100) for Capbyara drivers +you can initialize a new object. + +```ruby +class ActionSystemTestCase < ActionSystemTest::Base + ActionSystemTest.driver = ActionSystemTest::DriverAdapters::CapybaraDriver.new( + name: :poltergeist, + server: :webkit, + port: 3000 + ) +end +``` diff --git a/actionsystemtest/Rakefile b/actionsystemtest/Rakefile new file mode 100644 index 0000000000..8b07e8f4af --- /dev/null +++ b/actionsystemtest/Rakefile @@ -0,0 +1,32 @@ +require "rake/testtask" + +test_files = Dir.glob("test/**/*_test.rb") + +desc "Default Task" +task default: :test + +task :package + +# Run the unit tests +Rake::TestTask.new do |t| + t.libs << "test" + t.test_files = test_files + + t.warning = true + t.verbose = true + t.ruby_opts = ["--dev"] if defined?(JRUBY_VERSION) +end + +namespace :test do + task :isolated do + test_files.all? do |file| + sh(Gem.ruby, "-w", "-Ilib:test", file) + end || raise("Failures") + end +end + +task :lines do + load File.expand_path("..", File.dirname(__FILE__)) + "/tools/line_statistics" + files = FileList["lib/**/*.rb"] + CodeTools::LineStatistics.new(files).print_loc +end diff --git a/actionsystemtest/actionsystemtest.gemspec b/actionsystemtest/actionsystemtest.gemspec new file mode 100644 index 0000000000..81293980c4 --- /dev/null +++ b/actionsystemtest/actionsystemtest.gemspec @@ -0,0 +1,24 @@ +version = File.read(File.expand_path("../../RAILS_VERSION", __FILE__)).strip + +Gem::Specification.new do |s| + s.platform = Gem::Platform::RUBY + s.name = "actionsystemtest" + s.version = version + s.summary = "Acceptance test framework for Rails." + s.description = "Test framework for testing web applications by simulating how users interact with your application." + + s.required_ruby_version = ">= 2.2.2" + + s.license = "MIT" + + s.author = ["Eileen Uchitelle", "David Heinemeier Hansson"] + s.email = ["eileencodes@gmail.com", "david@loudthinking.com"] + s.homepage = "http://rubyonrails.org" + + s.files = Dir["CHANGELOG.md", "MIT-LICENSE", "README.md", "lib/**/*"] + s.require_path = "lib" + + s.add_dependency "capybara", "~> 2.7.0" + s.add_dependency "actionpack", version + s.add_dependency "activesupport", version +end diff --git a/actionsystemtest/lib/action_system_test.rb b/actionsystemtest/lib/action_system_test.rb new file mode 100644 index 0000000000..4a80e34695 --- /dev/null +++ b/actionsystemtest/lib/action_system_test.rb @@ -0,0 +1,59 @@ +require "action_system_test/test_helper" +require "action_system_test/driver_adapter" + +# System tests are similar to Integration tests in that they incorporate multiple +# controllers and actions, but can be used to simulate a real user experience. +# System tests are also known as Acceptance tests. +# +# To create a System Test in your application extend your test class from +# ActionSystemTestCase. System tests use Capybara as a base and +# allows you to configure the driver. The default driver is +# RailsSeleniumDriver which provides Capybara with no-setup +# configuration of the Selenium Driver. If you prefer you can use the bare +# Selenium driver and set your own configuration. +# +# A system test looks like the following: +# +# require 'test_helper' +# +# class Users::CreateTest < ActionSystemTestCase +# def adding_a_new_user +# visit users_path +# click_on 'New User' +# +# fill_in 'Name', with: 'Arya' +# click_on 'Create User' +# +# assert_text 'Arya' +# end +# end +# +# System test driver can be configured in your Rails configuration file for the +# test environment. +# +# config.system_testing.driver = :rails_selenium_driver +# +# You can also specify a driver by initializing a new driver object. This allows +# you to change the default settings for the driver you're setting. +# +# config.system_testing.driver = ActionSystemTest::DriverAdapters::RailsSeleniumDriver.new( +# browser: :firefox +# ) +# +# A list of supported adapters can be found in DriverAdapters. +# +# If you want to use one of the default drivers provided by Capybara you can +# set the driver in your config to one of those defaults: +:rack_test+, +# +:selenium+, +:webkit+, or +:poltergeist+. These 4 drivers use Capyara's +# driver defaults whereas the RailsSeleniumDriver has pre-set +# configuration for browser, server, port, etc. +module ActionSystemTest + include ActionSystemTest::TestHelper + include ActionSystemTest::DriverAdapter + + ActiveSupport.run_load_hooks(:system_testing, self) +end + +class ActionSystemTestCase < ActionDispatch::IntegrationTest + include ActionSystemTest +end diff --git a/actionsystemtest/lib/action_system_test/driver_adapter.rb b/actionsystemtest/lib/action_system_test/driver_adapter.rb new file mode 100644 index 0000000000..fe12ecaf80 --- /dev/null +++ b/actionsystemtest/lib/action_system_test/driver_adapter.rb @@ -0,0 +1,31 @@ +require "action_system_test/driver_adapters" + +module ActionSystemTest + # The ActionSystemTest::DriverAdapter module is used to load the driver + # set in your Rails' test configuration file. + # + # The default driver adapter is the +:rails_selenium_driver+. + module DriverAdapter + extend ActiveSupport::Concern + + module ClassMethods + def default_driver # :nodoc + :rails_selenium_driver + end + + # Returns the current driver that is set. If no driver is set in the + # Rails' configuration file then +:rails_selenium_driver+ will be + # initialized. + def driver + @driver ||= DriverAdapters.lookup(default_driver) + end + + # Specify the adapter and settings for the system test driver set in the + # Rails' configuration file. + def driver=(driver) + @driver = DriverAdapters.lookup(driver) + @driver.call + end + end + end +end diff --git a/actionsystemtest/lib/action_system_test/driver_adapters.rb b/actionsystemtest/lib/action_system_test/driver_adapters.rb new file mode 100644 index 0000000000..aead9d6f60 --- /dev/null +++ b/actionsystemtest/lib/action_system_test/driver_adapters.rb @@ -0,0 +1,46 @@ +module ActionSystemTest + # == System Testing Driver Adapters + # + # By default Rails supports Capybara with the Selenium Driver. Rails provides + # configuration setup for using the selenium driver with Capybara. + # Additionally Rails can be used as a layer between Capybara and its other + # supported drivers: +:rack_test+, +:selenium+, +:webkit+, or +:poltergeist+. + # + # *{RackTest}[https://github.com/jnicklas/capybara#racktest] + # *{Selenium}[http://seleniumhq.org/docs/01_introducing_selenium.html#selenium-2-aka-selenium-webdriver] + # *{Webkit}[https://github.com/thoughtbot/capybara-webkit] + # *{Poltergeist}[https://github.com/teampoltergeist/poltergeist] + # + # === Driver Features + # + # | | Default Browser | Supports Screenshots? | + # |-----------------|-----------------------|-----------------------| + # | Rails' Selenium | Chrome | Yes | + # | Rack Test | No JS Support | No | + # | Selenium | Firefox | Yes | + # | WebKit | Headless w/ Qt | Yes | + # | Poltergeist | Headless w/ PhantomJS | Yes | + module DriverAdapters + extend ActiveSupport::Autoload + + autoload :CapybaraDriver + autoload :RailsSeleniumDriver + + class << self + # Returns driver for specified name. + # + # ActionSystemTest::DriverAdapters.lookup(:rails_selenium_driver) + # # => ActionSystemTest::DriverAdapters::RailsSeleniumDriver + def lookup(driver) + if CapybaraDriver::CAPYBARA_DEFAULTS.include?(driver) + CapybaraDriver.new(name: driver) + elsif driver.is_a?(Symbol) + klass = const_get(driver.to_s.camelize) + klass.new + else + driver + end + end + end + end +end diff --git a/actionsystemtest/lib/action_system_test/driver_adapters/capybara_driver.rb b/actionsystemtest/lib/action_system_test/driver_adapters/capybara_driver.rb new file mode 100644 index 0000000000..5362f6db25 --- /dev/null +++ b/actionsystemtest/lib/action_system_test/driver_adapters/capybara_driver.rb @@ -0,0 +1,83 @@ +require "action_system_test/driver_adapters/web_server" + +module ActionSystemTest + module DriverAdapters + # == CapybaraDriver for System Testing + # + # The CapybaraDriver is a shim that sits between Rails and + # Capybara. + # + # The drivers Capybara supports are: +:rack_test+, +:selenium+, +:webkit+, + # and +:poltergeist+. + # + # Rails provides its own defaults for Capybara with the Selenium driver + # through RailsSeleniumDriver, but allows users to use Selenium + # directly. + # + # To set your system tests to use one of Capybara's default drivers, add + # the following to yur Rails' configuration test environment: + # + # config.system_testing.driver = :rack_test + # + # The +:rack_test+ driver is a basic test driver that doesn't support + # JavaScript testing and doesn't require a server. + # + # The +:poltergeist+ and +:webkit+ drivers are headless, but require some + # extra environment setup. Because the default server for Rails is Puma, each + # of the Capybara drivers will default to using Puma. Changing the configuration + # to use Webrick is possible by initalizing a new driver object. + # + # The default settings for the CapybaraDriver are: + # + # # + # + # The settings for the CapybaraDriver can be changed from + # Rails' configuration file. + # + # config.system_testing.driver = ActionSystemTest::DriverAdapters::CapybaraDriver.new( + # name: :webkit, + # server: :webrick + # ) + class CapybaraDriver + include WebServer + + CAPYBARA_DEFAULTS = [ :rack_test, :selenium, :webkit, :poltergeist ] + + attr_reader :name, :server, :port + + def initialize(name: :rack_test, server: :puma, port: 28100) + @name = name + @server = server + @port = port + end + + def call + registration + setup + end + + def supports_screenshots? + @name != :rack_test + end + + private + def registration + register_server + end + + def setup + set_server + set_port + set_driver + end + + def set_driver + Capybara.default_driver = @name + end + end + end +end diff --git a/actionsystemtest/lib/action_system_test/driver_adapters/rails_selenium_driver.rb b/actionsystemtest/lib/action_system_test/driver_adapters/rails_selenium_driver.rb new file mode 100644 index 0000000000..16e485398a --- /dev/null +++ b/actionsystemtest/lib/action_system_test/driver_adapters/rails_selenium_driver.rb @@ -0,0 +1,98 @@ +require "action_system_test/driver_adapters/web_server" + +module ActionSystemTest + module DriverAdapters + # == RailsSeleniumDriver for System Testing + # + # The RailsSeleniumDriver uses the Selenium 2.0 webdriver. The + # selenium-webdriver gem is required by this driver. + # + # The RailsSeleniumDriver is useful for real browser testing and + # supports Chrome and Firefox. + # + # By default Rails system testing will use Rails' configuration with Capybara + # and the Selenium driver. To explictly set the RailsSeleniumDriver + # add the following to your Rails' configuration test environment: + # + # config.system_testing.driver = :rails_selenium_driver + # + # Because this driver supports real browser testing it is required that a + # server is configured. + # + # If no server is specified when the driver is initialized, Puma will be used + # by default. The default settings for the RailsSeleniumDriver + # are as follows: + # + # # + # + # The settings for the RailsSeleniumDriver can be changed in the + # Rails configuration file. + # + # config.system_testing.driver = ActionSystemTest::DriverAdapters::RailsSeleniumDriver.new( + # server: :webrick, + # port: 28100, + # screen_size: [ 800, 800 ] + # ) + # + # The default browser is set to Chrome because the current version of + # Firefox does not work with selenium-webdriver. If you want to use Firefox, + # you will need to use Firefox 45.0esr or 47.0 and ensure + # that selenium-webdriver is version 2.53.4. To change the browser from + # +:chrome+ to +:firefox+, initialize the Selenium driver in your Rails' + # test environment: + # + # config.system_testing.driver = ActionSystemTest::DriverAdapters::RailsSeleniumDriver.new( + # browser: :firefox + # ) + class RailsSeleniumDriver + include WebServer + + attr_reader :browser, :server, :port, :screen_size + + def initialize(browser: :chrome, server: :puma, port: 28100, screen_size: [ 1400, 1400 ]) # :nodoc: + @browser = browser + @server = server + @port = port + @screen_size = screen_size + end + + def call # :nodoc: + registration + setup + end + + def supports_screenshots? + true + end + + private + def registration + register_browser_driver + register_server + end + + def setup + set_server + set_port + set_driver + end + + def register_browser_driver + Capybara.register_driver @browser do |app| + Capybara::Selenium::Driver.new(app, browser: @browser).tap do |driver| + driver.browser.manage.window.size = Selenium::WebDriver::Dimension.new(*@screen_size) + end + end + end + + def set_driver + Capybara.default_driver = @browser.to_sym + end + end + end +end diff --git a/actionsystemtest/lib/action_system_test/driver_adapters/web_server.rb b/actionsystemtest/lib/action_system_test/driver_adapters/web_server.rb new file mode 100644 index 0000000000..e115fe583c --- /dev/null +++ b/actionsystemtest/lib/action_system_test/driver_adapters/web_server.rb @@ -0,0 +1,45 @@ +begin + require "rack/handler/puma" +rescue LoadError + false +end + +module ActionSystemTest + module DriverAdapters + module WebServer # :nodoc: + def register_server + Capybara.register_server @server do |app, port, host| + case @server + when :puma + register_puma(app, port) + when :webrick + register_webrick(app, port) + else + register_default(app, port) + end + end + end + + private + def register_default(app, port) + Capybara.run_default_server(app, port) + end + + def register_puma(app, port) + Rack::Handler::Puma.run(app, Port: port, Threads: "0:4") + end + + def register_webrick(app, port) + Rack::Handler::WEBrick.run(app, Port: port) + end + + def set_server + Capybara.server = @server + end + + def set_port + Capybara.server_port = @port + end + end + end +end diff --git a/actionsystemtest/lib/action_system_test/gem_version.rb b/actionsystemtest/lib/action_system_test/gem_version.rb new file mode 100644 index 0000000000..c10fce2da0 --- /dev/null +++ b/actionsystemtest/lib/action_system_test/gem_version.rb @@ -0,0 +1,15 @@ +module ActionSystemTest + # Returns the version of the currently loaded Action System Test as a Gem::Version. + def self.gem_version + Gem::Version.new VERSION::STRING + end + + module VERSION + MAJOR = 5 + MINOR = 1 + TINY = 0 + PRE = "alpha" + + STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") + end +end diff --git a/actionsystemtest/lib/action_system_test/railtie.rb b/actionsystemtest/lib/action_system_test/railtie.rb new file mode 100644 index 0000000000..6f4fe1b993 --- /dev/null +++ b/actionsystemtest/lib/action_system_test/railtie.rb @@ -0,0 +1,17 @@ +require "action_system_test" + +module ActionSystemTest + # = System Testing Railtie + class Railtie < Rails::Railtie # :nodoc: + config.system_testing = ActiveSupport::OrderedOptions.new + + initializer "system_testing.set_configs" do |app| + options = app.config.system_testing + options.driver ||= ActionSystemTest.default_driver + + ActiveSupport.on_load(:system_testing) do + options.each { |k,v| send("#{k}=", v) } + end + end + end +end diff --git a/actionsystemtest/lib/action_system_test/test_helper.rb b/actionsystemtest/lib/action_system_test/test_helper.rb new file mode 100644 index 0000000000..428f0faeca --- /dev/null +++ b/actionsystemtest/lib/action_system_test/test_helper.rb @@ -0,0 +1,23 @@ +require "capybara/dsl" +require "action_system_test/test_helpers" + +module ActionSystemTest + module TestHelper # :nodoc: + include TestHelpers::Assertions + include TestHelpers::FormHelper + include TestHelpers::ScreenshotHelper + include Capybara::DSL + + Capybara.app = Rack::Builder.new do + map "/" do + run Rails.application + end + end + + def after_teardown + take_screenshot if supported? + Capybara.reset_sessions! + super + end + end +end diff --git a/actionsystemtest/lib/action_system_test/test_helpers.rb b/actionsystemtest/lib/action_system_test/test_helpers.rb new file mode 100644 index 0000000000..10ddeff92f --- /dev/null +++ b/actionsystemtest/lib/action_system_test/test_helpers.rb @@ -0,0 +1,9 @@ +module ActionSystemTest + module TestHelpers + extend ActiveSupport::Autoload + + autoload :Assertions + autoload :FormHelper + autoload :ScreenshotHelper + end +end diff --git a/actionsystemtest/lib/action_system_test/test_helpers/assertions.rb b/actionsystemtest/lib/action_system_test/test_helpers/assertions.rb new file mode 100644 index 0000000000..edc8dbaa7f --- /dev/null +++ b/actionsystemtest/lib/action_system_test/test_helpers/assertions.rb @@ -0,0 +1,40 @@ +module ActionSystemTest + module TestHelpers + # Assertions for system testing that aren't included by default in Capybara. + # These are assertions that are useful specifically for Rails applications. + module Assertions + # Asserts that all of the provided selectors are present on the given page. + # + # assert_all_of_selectors('p', 'td') + def assert_all_of_selectors(*items) + options = items.extract_options! + type = type_for_selector(items) + + items.each do |item| + assert_selector type, item, options + end + end + + # Asserts that none of the provided selectors are present on the page. + # + # assert_none_of_selectors('ul', 'ol') + def assert_none_of_selectors(*items) + options = items.extract_options! + type = type_for_selector(items) + + items.each do |item| + assert_no_selector type, item, options + end + end + + private + def type_for_selector(*items) + if items.first.is_a?(Symbol) + items.shift + else + Capybara.default_selector + end + end + end + end +end diff --git a/actionsystemtest/lib/action_system_test/test_helpers/form_helper.rb b/actionsystemtest/lib/action_system_test/test_helpers/form_helper.rb new file mode 100644 index 0000000000..3c65c23f6d --- /dev/null +++ b/actionsystemtest/lib/action_system_test/test_helpers/form_helper.rb @@ -0,0 +1,58 @@ +module ActionSystemTest + module TestHelpers + # Form helpers for system testing that aren't included by default in + # Capybara. + module FormHelper + # Finds all provided fields or text areas and fills in with supplied values. + # + # fill_in_all_fields('Name' => 'Eileen', 'Job Title' => 'Programmer') + def fill_in_all_fields(fields) + fields.each do |name, value| + fill_in name, with: value + end + end + + # Locates a checkbox that is present inside a label and checks it. When + # using styled boxes Selenium may not be able to see the checkbox. This + # form helper looks inside the checkbox and clicks the label instead of + # setting the value of the checkbox. + # + # click_checkbox_label 'Admin' + # + # By default +click_checkbox_label+ looks for checkboxes that are not + # checked by default. To locate an already checked box and uncheck it + # set checked to true: + # + # click_checkbox_label 'Admin', checked: true + def click_checkbox_label(name, checked: false) + field = find_checkbox(name, checked) + label = find_label_wrapper(field) + label.click + end + + # In lieu of locating a button and calling +click_on+, +press_enter+ will + # submit the form via enter. This method will only work for drivers that + # load a browser like Selenium. + # + # test 'Adding a User' do + # fill_in 'Name', with: 'Arya' + # + # press_enter + # + # assert_text 'Arya' + # end + def press_enter + page.driver.browser.action.send_keys(:enter).perform + end + + private + def find_checkbox(name, checked) + find(:field, name, visible: :all, checked: checked) + end + + def find_label_wrapper(field, location: "./ancestor::label") + field.find :xpath, location + end + end + end +end diff --git a/actionsystemtest/lib/action_system_test/test_helpers/screenshot_helper.rb b/actionsystemtest/lib/action_system_test/test_helpers/screenshot_helper.rb new file mode 100644 index 0000000000..37336e976f --- /dev/null +++ b/actionsystemtest/lib/action_system_test/test_helpers/screenshot_helper.rb @@ -0,0 +1,47 @@ +module ActionSystemTest + module TestHelpers + # Screenshot helper for system testing + module ScreenshotHelper + # Takes a screenshot of the current page in the browser if the system + # test driver supports screenshots and the test failed. + # + # Additionally +take_screenshot+ can be used within your tests at points + # you want to take a screenshot if the driver supports screenshots. The + # Rack Test driver does not support screenshots. + # + # You can check of the driver supports screenshots by running + # + # ActionSystemTest.driver.supports_screenshots? + # => true + def take_screenshot + puts "[Screenshot]: #{image_path}" + puts find_image + end + + private + def supported? + ActionSystemTest.driver.supports_screenshots? && !passed? + end + + def image_path + path = "tmp/screenshots/failures_#{method_name}.png" + page.save_screenshot(Rails.root.join(path)) + path + end + + def find_image + if ENV["CAPYBARA_INLINE_SCREENSHOT"] == "artifact" + "\e]1338;url=artifact://#{image_path}\a" + else + name = inline_base64(File.basename(image_path)) + image = inline_base64(File.read(image_path)) + "\e]1337;File=name=#{name};height=400px;inline=1:#{image}\a" + end + end + + def inline_base64(path) + Base64.encode64(path).gsub("\n", "") + end + end + end +end diff --git a/actionsystemtest/lib/action_system_test/version.rb b/actionsystemtest/lib/action_system_test/version.rb new file mode 100644 index 0000000000..a0fda7d9da --- /dev/null +++ b/actionsystemtest/lib/action_system_test/version.rb @@ -0,0 +1,8 @@ +require_relative "gem_version" + +module ActionSystemTest + # Returns the version of the currently loaded Action System Test as a Gem::Version + def self.version + gem_version + end +end diff --git a/actionsystemtest/test/abstract_unit.rb b/actionsystemtest/test/abstract_unit.rb new file mode 100644 index 0000000000..26da9c7ccb --- /dev/null +++ b/actionsystemtest/test/abstract_unit.rb @@ -0,0 +1,13 @@ +require "active_support/testing/autorun" +require "action_controller" +require "action_dispatch" +require "action_system_test" + +# Skips the current run on Rubinius using Minitest::Assertions#skip +def rubinius_skip(message = "") + skip message if RUBY_ENGINE == "rbx" +end +# Skips the current run on JRuby using Minitest::Assertions#skip +def jruby_skip(message = "") + skip message if defined?(JRUBY_VERSION) +end diff --git a/actionsystemtest/test/cases/capybara_driver_test.rb b/actionsystemtest/test/cases/capybara_driver_test.rb new file mode 100644 index 0000000000..33337ad18b --- /dev/null +++ b/actionsystemtest/test/cases/capybara_driver_test.rb @@ -0,0 +1,39 @@ +require "abstract_unit" + +class CapybaraDriverTest < ActiveSupport::TestCase + def setup + ActionSystemTest.driver = :poltergeist + end + + def test_default_driver_adapter + assert_kind_of ActionSystemTest::DriverAdapters::CapybaraDriver, ActionSystemTest.driver + end + + def test_default_settings + assert_equal :poltergeist, ActionSystemTest.driver.name + assert_equal :puma, ActionSystemTest.driver.server + assert_equal 28100, ActionSystemTest.driver.port + end + + def test_setting_driver + ActionSystemTest.driver = :webkit + + assert_equal :webkit, ActionSystemTest.driver.name + end + + def test_setting_server + ActionSystemTest.driver = ActionSystemTest::DriverAdapters::CapybaraDriver.new( + server: :webrick + ) + + assert_equal :webrick, ActionSystemTest.driver.server + end + + def test_setting_port + ActionSystemTest.driver = ActionSystemTest::DriverAdapters::CapybaraDriver.new( + port: 3000 + ) + + assert_equal 3000, ActionSystemTest.driver.port + end +end diff --git a/actionsystemtest/test/cases/driver_adapter_test.rb b/actionsystemtest/test/cases/driver_adapter_test.rb new file mode 100644 index 0000000000..cecaa5b958 --- /dev/null +++ b/actionsystemtest/test/cases/driver_adapter_test.rb @@ -0,0 +1,13 @@ +require "abstract_unit" + +class DriverAdapterTest < ActiveSupport::TestCase + test "only registered adapters are accepted" do + assert_raises(NameError) do + ActionSystemTest.driver = :whatever + end + + assert_nothing_raised do + ActionSystemTest.driver = :rack_test + end + end +end diff --git a/actionsystemtest/test/cases/rails_selenium_driver_test.rb b/actionsystemtest/test/cases/rails_selenium_driver_test.rb new file mode 100644 index 0000000000..1a8e875f52 --- /dev/null +++ b/actionsystemtest/test/cases/rails_selenium_driver_test.rb @@ -0,0 +1,11 @@ +require "abstract_unit" + +class RailsSeleniumDriverTest < ActiveSupport::TestCase + def setup + ActionSystemTest.driver = :rails_selenium_driver + end + + def test_default_driver_adapter + assert_kind_of ActionSystemTest::DriverAdapters::RailsSeleniumDriver, ActionSystemTest.driver + end +end diff --git a/actionsystemtest/test/cases/screenshot_helper_test.rb b/actionsystemtest/test/cases/screenshot_helper_test.rb new file mode 100644 index 0000000000..43b24cba21 --- /dev/null +++ b/actionsystemtest/test/cases/screenshot_helper_test.rb @@ -0,0 +1,20 @@ +require "abstract_unit" + +class ScreenshotHelperTest < ActiveSupport::TestCase + def test_driver_support_for_screenshots + ActionSystemTest.driver = :rails_selenium_driver + assert ActionSystemTest.driver.supports_screenshots? + + ActionSystemTest.driver = :rack_test + assert_not ActionSystemTest.driver.supports_screenshots? + + ActionSystemTest.driver = :selenium + assert ActionSystemTest.driver.supports_screenshots? + + ActionSystemTest.driver = :webkit + assert ActionSystemTest.driver.supports_screenshots? + + ActionSystemTest.driver = :poltergeist + assert ActionSystemTest.driver.supports_screenshots? + end +end -- cgit v1.2.3