Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/gem-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
50 changes: 27 additions & 23 deletions lib/dvla/browser/drivers/meta_drivers.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
module DVLA
module Browser
module Drivers
DRIVER_REGEX = /^(?:(?<headless>headless)_)?(?<driver>(selenium_(?<browser>chrome|firefox|edge)|cuprite|apparition))$/
DRIVER_REGEX = /^(?:(?<headless>headless_)(?<driver>selenium_(?<browser>chrome|firefox)|cuprite|apparition)|(?<driver_no_headless>selenium_(?<browser_no_headless>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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/dvla/browser/drivers/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module DVLA
module Browser
module Drivers
VERSION = '3.1.0'
VERSION = '3.1.1'
end
end
end
4 changes: 3 additions & 1 deletion spec/dvla/browser/drivers_bidi_spec.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
50 changes: 36 additions & 14 deletions spec/dvla/browser/drivers_spec.rb
Original file line number Diff line number Diff line change
@@ -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)

Expand All @@ -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)

Expand All @@ -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
Expand All @@ -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
Loading