From ec07a3cd3dea5dd229eab7ceb668d5579d054ec0 Mon Sep 17 00:00:00 2001 From: filipefurtad0 Date: Tue, 20 Jul 2021 15:52:21 +0100 Subject: [PATCH] Add the Ferrum-Cuprite driver to the stack --- Gemfile | 1 + spec/system/first_system_spec.rb | 23 +++++++ .../support/better_rails_system_tests.rb | 45 +++++++++++++ spec/system/support/capybara_setup.rb | 28 ++++++++ spec/system/support/cuprite_setup.rb | 44 +++++++++++++ spec/system/support/precompile_assets.rb | 65 +++++++++++++++++++ spec/system_helper.rb | 6 ++ 7 files changed, 212 insertions(+) create mode 100644 spec/system/first_system_spec.rb create mode 100644 spec/system/support/better_rails_system_tests.rb create mode 100644 spec/system/support/capybara_setup.rb create mode 100644 spec/system/support/cuprite_setup.rb create mode 100644 spec/system/support/precompile_assets.rb create mode 100644 spec/system_helper.rb diff --git a/Gemfile b/Gemfile index 3df788509a..a85c2e0ffe 100644 --- a/Gemfile +++ b/Gemfile @@ -150,6 +150,7 @@ group :test, :development do gem 'timecop' gem 'unicorn-rails' gem 'webdrivers' + gem 'cuprite' end group :test do diff --git a/spec/system/first_system_spec.rb b/spec/system/first_system_spec.rb new file mode 100644 index 0000000000..7ed33b80f3 --- /dev/null +++ b/spec/system/first_system_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require "system_helper" + +feature "visit admin", js: true do + include UIComponentHelper + include AuthenticationHelper + include WebHelper + let(:user) { create(:user, password: "password", password_confirmation: "password") } + let!(:enterprise) { create(:enterprise, owner: user) } # Required for access to admin + + scenario "logging into admin redirects home, then back to admin" do + visit spree.admin_dashboard_path + + fill_in "Email", with: user.email + fill_in "Password", with: user.password + + click_login_button + expect(page).to have_content "DASHBOARD" + expect(page).to have_current_path spree.admin_dashboard_path + expect(page).to have_no_content "CONFIGURATION" + end +end \ No newline at end of file diff --git a/spec/system/support/better_rails_system_tests.rb b/spec/system/support/better_rails_system_tests.rb new file mode 100644 index 0000000000..2b5828f778 --- /dev/null +++ b/spec/system/support/better_rails_system_tests.rb @@ -0,0 +1,45 @@ +# spec/system/support/better_rails_system_tests.rb + +module BetterRailsSystemTests + # Use our `Capybara.save_path` to store screenshots with other capybara artifacts + # (Rails screenshots path is not configurable https://github.com/rails/rails/blob/49baf092439fc74fc3377b12e3334c3dd9d0752f/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb#L79) + def absolute_image_path + Rails.root.join("#{Capybara.save_path}/screenshots/#{image_name}.png") + end + + # Make failure screenshots compatible with multi-session setup. + # That's where we use Capybara.last_used_session introduced before. + def take_screenshot + return super unless Capybara.last_used_session + + Capybara.using_session(Capybara.last_used_session) { super } + end + + ## Use relative path in screenshot message + ##def image_path + ## absolute_image_path.relative_path_from(Rails.root).to_s + ##end + +end + +RSpec.configure do |config| + config.include BetterRailsSystemTests, type: :system + + # Make urls in mailers contain the correct server host. + # It's required for testing links in emails (e.g., via capybara-email). + config.around(:each, type: :system) do |ex| + was_host = Rails.application.default_url_options[:host] + Rails.application.default_url_options[:host] = Capybara.server_host + ex.run + Rails.application.default_url_options[:host] = was_host + end + + # Make sure this hook runs before others + config.prepend_before(:each, type: :system) do + # Rails sets host to `127.0.0.1` for every test by default. + # That won't work with a remote browser. + host! CAPYBARA_APP_HOST + # Use JS driver always + driven_by Capybara.javascript_driver + end +end diff --git a/spec/system/support/capybara_setup.rb b/spec/system/support/capybara_setup.rb new file mode 100644 index 0000000000..c631bcb2eb --- /dev/null +++ b/spec/system/support/capybara_setup.rb @@ -0,0 +1,28 @@ +# spec/system/support/capybara_setup.rb + +# Usually, especially when using Selenium, developers tend to increase the max wait time. +# With Cuprite, there is no need for that. +# We use a Capybara default value here explicitly. +Capybara.default_max_wait_time = 2 + +# Normalize whitespaces when using `has_text?` and similar matchers, +# i.e., ignore newlines, trailing spaces, etc. +# That makes tests less dependent on slightly UI changes. +Capybara.default_normalize_ws = true + +# Where to store system tests artifacts (e.g. screenshots, downloaded files, etc.). +# It could be useful to be able to configure this path from the outside (e.g., on CI). +Capybara.save_path = ENV.fetch("CAPYBARA_ARTIFACTS", "./tmp/capybara") + +# spec/system/support/capybara_setup.rb + +Capybara.singleton_class.prepend(Module.new do + attr_accessor :last_used_session + + def using_session(name, &block) + self.last_used_session = name + super + ensure + self.last_used_session = nil + end +end) diff --git a/spec/system/support/cuprite_setup.rb b/spec/system/support/cuprite_setup.rb new file mode 100644 index 0000000000..3b3ea6f6d8 --- /dev/null +++ b/spec/system/support/cuprite_setup.rb @@ -0,0 +1,44 @@ +# spec/system/support/cuprite_setup.rb + +# First, load Cuprite Capybara integration +require "capybara/cuprite" + +# Then, we need to register our driver to be able to use it later +# with #driven_by method. +Capybara.register_driver(:cuprite) do |app| + Capybara::Cuprite::Driver.new( + app, + **{ + window_size: [1200, 800], + # See additional options for Dockerized environment in the respective section of this article + browser_options: {}, + # Increase Chrome startup wait time (required for stable CI builds) + process_timeout: 10, + # Enable debugging capabilities + inspector: true, + # Allow running Chrome in a headful mode by setting HEADLESS env + headless: false + } + ) +end + +# Configure Capybara to use :cuprite driver by default +Capybara.default_driver = Capybara.javascript_driver = :cuprite + +module CupriteHelpers + # Drop #pause anywhere in a test to stop the execution. + # Useful when you want to checkout the contents of a web page in the middle of a test + # running in a headful mode. + def pause + page.driver.pause + end + + # Drop #debug anywhere in a test to open a Chrome inspector and pause the execution + def debug(*args) + page.driver.debug(*args) + end +end + +RSpec.configure do |config| + config.include CupriteHelpers, type: :system +end diff --git a/spec/system/support/precompile_assets.rb b/spec/system/support/precompile_assets.rb new file mode 100644 index 0000000000..7d6d7ccdeb --- /dev/null +++ b/spec/system/support/precompile_assets.rb @@ -0,0 +1,65 @@ +RSpec.configure do |config| + # Skip assets precompilcation if we exclude system specs. + # For example, you can run all non-system tests via the following command: + # + # rspec --tag ~type:system + # + # In this case, we don't need to precompile assets. + next if config.filter.opposite.rules[:type] == "system" || config.exclude_pattern.match?(%r{spec/system}) + + config.before(:suite) do + # We can use webpack-dev-server for tests, too! + # Useful if you working on a frontend code fixes and want to verify them via system tests. + if Webpacker.dev_server.running? + $stdout.puts "\n⚙️ Webpack dev server is running! Skip assets compilation.\n" + next + else + $stdout.puts "\n🐢 Precompiling assets.\n" + + # The code to run webpacker:compile Rake task + # ... + end + end +end + +=begin + +# frozen_string_literal: true + +# Precompile assets before running tests to avoid timeouts. +# Do not precompile if webpack-dev-server is running (NOTE: MUST be launched with RAILS_ENV=test) +RSpec.configure do |config| + config.before(:suite) do + examples = RSpec.world.filtered_examples.values.flatten + has_no_system_tests = examples.none? { |example| example.metadata[:type] == :system } + + if has_no_system_tests + $stdout.puts "\n🚀️️ No system test selected. Skip assets compilation.\n" + next + end + + if Webpacker.dev_server.running? + $stdout.puts "\n⚙️ Webpack dev server is running! Skip assets compilation.\n" + next + else + $stdout.puts "\n🐢 Precompiling assets.\n" + original_stdout = $stdout.clone + # Use test-prof now 'cause it couldn't be monkey-patched (e.g., by Timecop or similar) + start = Time.current + begin + # Silence Webpacker output + $stdout.reopen(File.new("/dev/null", "w")) + # next 3 lines to compile webpacker before running our test suite + require "rake" + Rails.application.load_tasks + Rake::Task["webpacker:compile"].execute + ensure + $stdout.reopen(original_stdout) + $stdout.puts "Finished in #{(Time.current - start).round(2)} seconds" + end + end + end +end + +=end + diff --git a/spec/system_helper.rb b/spec/system_helper.rb new file mode 100644 index 0000000000..354b413b49 --- /dev/null +++ b/spec/system_helper.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +require "rails_helper" + +# system/support/ files contain system tests configurations and helpers +Dir[File.join(__dir__, "system/support/**/*.rb")].sort.each { |file| require file }