diff --git a/.github/workflows/gem-test.yml b/.github/workflows/gem-test.yml index e5f6a85..227d8fe 100644 --- a/.github/workflows/gem-test.yml +++ b/.github/workflows/gem-test.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: ["3.1", "3.2", "3.3"] + ruby-version: ["3.1", "3.2", "3.3", "3.4"] steps: - uses: actions/checkout@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index b9e07de..b80b376 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog All notable changes to this project will be documented in this file. +# [3.1.1] - 2025-12-12 + +- Add selenium_safari config +- Add optional binary string for Selenium # [3.1.0] - 2025-12-10 diff --git a/README.md b/README.md index 11e4fcd..26da471 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,10 @@ Once installed, you are able to use any pre-configured browser driver from the l |---------------------------|----------------------------------------------------| | selenium_chrome | `DVLA::Browser::Drivers.selenium_chrome` | | headless_selenium_chrome | `DVLA::Browser::Drivers.headless_selenium_chrome` | -| selenium_edge | `DVLA::Browser::Drivers.selenium_edge` | -| headless_selenium_edge | `DVLA::Browser::Drivers.headless_selenium_edge` | | selenium_firefox | `DVLA::Browser::Drivers.selenium_firefox` | | headless_selenium_firefox | `DVLA::Browser::Drivers.headless_selenium_firefox` | +| selenium_edge | `DVLA::Browser::Drivers.selenium_edge` | +| selenium_safari | `DVLA::Browser::Drivers.selenium_safari` | ### Non-selenium drivers @@ -43,6 +43,8 @@ Once installed, you are able to use any pre-configured browser driver from the l | apparition | `DVLA::Browser::Drivers.apparition` | | headless_apparition | `DVLA::Browser::Drivers.headless_apparition` | +**Note:** Safari and Edge do not support headless mode. + --- ### Default configuration diff --git a/lib/dvla/browser/drivers/meta_drivers.rb b/lib/dvla/browser/drivers/meta_drivers.rb index 2fec8d4..50f26d2 100644 --- a/lib/dvla/browser/drivers/meta_drivers.rb +++ b/lib/dvla/browser/drivers/meta_drivers.rb @@ -1,12 +1,12 @@ module DVLA module Browser module Drivers - DRIVER_REGEX = /^(?:(?headless)_)?(?(selenium_(?chrome|firefox|edge)|cuprite|apparition))$/ + DRIVER_REGEX = /^(?:(?headless_)(?selenium_(?chrome|firefox)|cuprite|apparition)|(?selenium_(?chrome|firefox|edge|safari)|cuprite|apparition))$/ OTHER_ACCEPTED_PARAMS = %i[timeout browser_options save_path remote].freeze OTHER_DRIVERS = %i[cuprite apparition].freeze - SELENIUM_ACCEPTED_PARAMS = %i[remote additional_arguments additional_preferences].freeze - SELENIUM_DRIVERS = %i[selenium_chrome selenium_firefox selenium_edge].freeze + SELENIUM_ACCEPTED_PARAMS = %i[remote additional_arguments additional_preferences binary].freeze + SELENIUM_DRIVERS = %i[selenium_chrome selenium_firefox selenium_edge selenium_safari].freeze # Creates methods in the Drivers module that matches the DRIVER_REGEX # These methods will register a Driver for use by Capybara in a test pack @@ -19,35 +19,39 @@ module Drivers def self.method_missing(method, *args, **kwargs, &) if (matches = method.match(DRIVER_REGEX)) headless = matches[:headless].is_a? String - driver = matches[:driver].to_sym + driver = matches[:driver]&.to_sym || matches[:driver_no_headless]&.to_sym + browser_match = matches[:browser] || matches[:browser_no_headless] case driver when *SELENIUM_DRIVERS - browser = matches[:browser].to_sym + browser = browser_match.to_sym kwargs.each do |key, _value| LOG.warn { "Key: '#{key}' will be ignored | Use one from: '#{SELENIUM_ACCEPTED_PARAMS}'" } unless SELENIUM_ACCEPTED_PARAMS.include?(key) end ::Capybara.register_driver method do |app| - options = Object.const_get("Selenium::WebDriver::#{browser.to_s.capitalize}::Options").new(web_socket_url: true) - options.add_argument('--disable-dev-shm-usage') - - if headless - options.add_argument('--headless') - options.add_argument('--no-sandbox') - end - - browser = :remote if kwargs[:remote] - - kwargs[:additional_arguments] && kwargs[:additional_arguments].each do |argument| - argument.prepend('--') unless argument.start_with?('--') - options.add_argument(argument) - end - - kwargs[:additional_preferences] && kwargs[:additional_preferences].each do |preference| - key, value = preference.first - options.add_preference(key, value) + if browser == :safari + options = Selenium::WebDriver::Safari::Options.new + else + options = Object.const_get("Selenium::WebDriver::#{browser.to_s.capitalize}::Options").new(web_socket_url: true) + options.binary = kwargs[:binary] if kwargs[:binary] + options.add_argument('--disable-dev-shm-usage') + + if headless + options.add_argument('--headless') + options.add_argument('--no-sandbox') + end + + kwargs[:additional_arguments] && kwargs[:additional_arguments].each do |argument| + argument.prepend('--') unless argument.start_with?('--') + options.add_argument(argument) + end + + kwargs[:additional_preferences] && kwargs[:additional_preferences].each do |preference| + key, value = preference.first + options.add_preference(key, value) + end end driver_browser = kwargs[:remote] ? :remote : browser diff --git a/lib/dvla/browser/drivers/version.rb b/lib/dvla/browser/drivers/version.rb index 50eeb7c..d00e8f5 100644 --- a/lib/dvla/browser/drivers/version.rb +++ b/lib/dvla/browser/drivers/version.rb @@ -3,7 +3,7 @@ module DVLA module Browser module Drivers - VERSION = '3.1.0' + VERSION = '3.1.1' end end end diff --git a/spec/dvla/browser/drivers_bidi_spec.rb b/spec/dvla/browser/drivers_bidi_spec.rb index b4b5af4..affac6a 100644 --- a/spec/dvla/browser/drivers_bidi_spec.rb +++ b/spec/dvla/browser/drivers_bidi_spec.rb @@ -1,15 +1,17 @@ # frozen_string_literal: true RSpec.describe 'DVLA::Browser::Drivers BiDi Support' do - %i[headless_selenium_chrome headless_selenium_firefox headless_selenium_edge].each do |driver| + %i[headless_selenium_chrome headless_selenium_firefox selenium_edge].each do |driver| describe "BiDi functionality with #{driver}", :bidi_integration do before do + skip 'Edge WebDriver not available in CI' if driver == :selenium_edge && ENV['CI'] DVLA::Browser::Drivers.send(driver) Capybara.current_driver = driver end after do Capybara.reset_sessions! + Capybara.instance_variable_set(:@session_pool, nil) end it 'provides BiDi instance by default' do diff --git a/spec/dvla/browser/drivers_spec.rb b/spec/dvla/browser/drivers_spec.rb index 602c9c9..bdc78bc 100644 --- a/spec/dvla/browser/drivers_spec.rb +++ b/spec/dvla/browser/drivers_spec.rb @@ -1,34 +1,44 @@ RSpec.describe DVLA::Browser::Drivers do + after do + Capybara.reset_sessions! + Capybara.instance_variable_set(:@session_pool, nil) + end + it 'has a version number' do expect(DVLA::Browser::Drivers::VERSION).not_to be nil end - it 'can create a chrome driver' do + it 'can create a Chrome driver' do DVLA::Browser::Drivers.selenium_chrome expect(Capybara.current_driver).to eq(:selenium_chrome) end - it 'can create a firefox driver' do + it 'can create a Firefox driver' do DVLA::Browser::Drivers.selenium_firefox expect(Capybara.current_driver).to eq(:selenium_firefox) end - it 'can create an edge driver' do + it 'can create an Edge driver' do DVLA::Browser::Drivers.selenium_edge expect(Capybara.current_driver).to eq(:selenium_edge) end - it 'can create a cuprite driver' do + it 'can create a Safari driver' do + DVLA::Browser::Drivers.selenium_safari + expect(Capybara.current_driver).to eq(:selenium_safari) + end + + it 'can create a Cuprite driver' do DVLA::Browser::Drivers.cuprite expect(Capybara.current_driver).to eq(:cuprite) end - it 'can create an apparition driver' do + it 'can create an Apparition driver' do DVLA::Browser::Drivers.apparition expect(Capybara.current_driver).to eq(:apparition) end - it 'can create a headless chrome driver with standard options' do + it 'can create a headless Chrome driver with standard options' do DVLA::Browser::Drivers.headless_selenium_chrome expect(Capybara.current_driver).to eq(:headless_selenium_chrome) @@ -39,22 +49,25 @@ expect(args).to include('--no-sandbox') end - it 'can create a headless firefox driver' do + it 'can create a headless Firefox driver' do DVLA::Browser::Drivers.headless_selenium_firefox expect(Capybara.current_driver).to eq(:headless_selenium_firefox) end - it 'can create a headless edge driver' do - DVLA::Browser::Drivers.headless_selenium_edge - expect(Capybara.current_driver).to eq(:headless_selenium_edge) + it 'does not create an Edge driver with headless configuration' do + expect { DVLA::Browser::Drivers.headless_selenium_edge }.to raise_error NoMethodError + end + + it 'does not create a Safari driver with headless configuration' do + expect { DVLA::Browser::Drivers.headless_selenium_safari }.to raise_error NoMethodError end - it 'can create a headless apparition driver' do + it 'can create a headless Apparition driver' do DVLA::Browser::Drivers.headless_apparition expect(Capybara.current_driver).to eq(:headless_apparition) end - it 'can create a headless cuprite driver with standard options' do + it 'can create a headless Cuprite driver with standard options' do DVLA::Browser::Drivers.headless_cuprite expect(Capybara.current_driver).to eq(:headless_cuprite) @@ -65,17 +78,23 @@ expect(options.dig(:browser_options, :'disable-smooth-scrolling')).to eq(true) end - it 'allows additional args to be passed' do + it 'allows Chrome to accept remote argument' do DVLA::Browser::Drivers.selenium_chrome(remote: 'hello_world') expect(Capybara.current_session.driver.options[:url]).to eq('hello_world') expect(Capybara.current_session.driver.options[:browser]).to eq(:remote) + end + it 'allows Firefox to accept additional arguments' do DVLA::Browser::Drivers.selenium_firefox(additional_arguments: %w[headless]) expect(Capybara.current_session.driver.options[:options].options[:args]).to include('--headless') + end + it 'allows Edge to accept additional preferences' do DVLA::Browser::Drivers.selenium_edge(additional_preferences: [{ key: 'value' }]) expect(Capybara.current_session.driver.options[:options].prefs).to include({ key: 'value' }) + end + it 'allows Cuprite to accept timeout and browser options' do DVLA::Browser::Drivers.cuprite(timeout: 5, browser_options: { something: 'blah' }) expect(Capybara.current_session.driver.options.dig(:browser_options, :something)).to eq('blah') end @@ -88,13 +107,16 @@ expect(DVLA::Browser::Drivers.respond_to?(:selenium_chrome)).to be true expect(DVLA::Browser::Drivers.respond_to?(:selenium_edge)).to be true expect(DVLA::Browser::Drivers.respond_to?(:selenium_firefox)).to be true + expect(DVLA::Browser::Drivers.respond_to?(:selenium_safari)).to be true expect(DVLA::Browser::Drivers.respond_to?(:cuprite)).to be true expect(DVLA::Browser::Drivers.respond_to?(:apparition)).to be true expect(DVLA::Browser::Drivers.respond_to?(:headless_selenium_chrome)).to be true - expect(DVLA::Browser::Drivers.respond_to?(:headless_selenium_edge)).to be true expect(DVLA::Browser::Drivers.respond_to?(:headless_selenium_firefox)).to be true expect(DVLA::Browser::Drivers.respond_to?(:headless_cuprite)).to be true expect(DVLA::Browser::Drivers.respond_to?(:headless_apparition)).to be true + + expect(DVLA::Browser::Drivers.respond_to?(:headless_selenium_edge)).to be false + expect(DVLA::Browser::Drivers.respond_to?(:headless_selenium_safari)).to be false end end