Skip to content

Commit

Permalink
Allow to enable/disable use of native displayed
Browse files Browse the repository at this point in the history
  • Loading branch information
twalpole committed Jul 26, 2019
1 parent 28d845f commit 6d3fff1
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 4 deletions.
6 changes: 6 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Version 3.27.0
Release date: unreleased

### Added

* Allow to use chromedriver/geckodriver native `is_element_displayed` endpoint via Selenium
driver `native_displayed` option for performance reasons. Disabled by default due to endpoints
currently not handling <details> element descendants visibility correctly.

### Fixed

* Ignore negative lookahead/lookbehind regex when performing initial XPath text matching
Expand Down
2 changes: 1 addition & 1 deletion lib/capybara/selenium/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
clear_local_storage: nil,
clear_session_storage: nil
}.freeze
SPECIAL_OPTIONS = %i[browser clear_local_storage clear_session_storage timeout].freeze
SPECIAL_OPTIONS = %i[browser clear_local_storage clear_session_storage timeout native_displayed].freeze
attr_reader :app, :options

class << self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def self.extended(base)
bridge = base.send(:bridge)
bridge.extend Capybara::Selenium::ChromeLogs unless bridge.respond_to?(:log)
bridge.extend Capybara::Selenium::IsDisplayed unless bridge.commands(:is_element_displayed)
base.options[:native_displayed] = false if base.options[:native_displayed].nil?
end

def fullscreen_window(handle)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module Capybara::Selenium::Driver::W3CFirefoxDriver
class << self
def extended(driver)
require 'capybara/selenium/patches/pause_duration_fix' if pause_broken?(driver.browser)
driver.options[:native_displayed] = false if driver.options[:native_displayed].nil?
end

def pause_broken?(sel_driver)
Expand Down
16 changes: 13 additions & 3 deletions lib/capybara/selenium/nodes/firefox_node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,23 @@ def select_option
end

def visible?
return super if ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS']

bridge.send(:execute, :is_element_displayed, id: native.ref)
return super unless native_displayed?

begin
bridge.send(:execute, :is_element_displayed, id: native.ref)
rescue Selenium::WebDriver::Error::UnknownCommandError
# If the is_element_displayed command is unknown, no point in trying again
driver.options[:native_displayed] = false
super
end
end

private

def native_displayed?
(driver.options[:native_displayed] != false) && !ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS']
end

def click_with_options(click_options)
# Firefox/marionette has an issue clicking with offset near viewport edge
# scroll element to middle just in case
Expand Down
36 changes: 36 additions & 0 deletions spec/shared_selenium_node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,40 @@
expect(session.find(:css, '#address1_city').value).to eq 'ocean SIDE'
end
end

context '#visible?' do
let(:bridge) do
session.driver.browser.send(:bridge)
end

around do |example|
native_displayed = session.driver.options[:native_displayed]
example.run
session.driver.options[:native_displayed] = native_displayed
end

before do
allow(bridge).to receive(:execute_atom).and_call_original
end

it 'will use native displayed if told to' do
pending "Chromedriver < 76.0.3809.25 doesn't support native displayed in W3C mode" if chrome_lt?(76, session) && (ENV['W3C'] != 'false')

session.driver.options[:native_displayed] = true
session.visit('/form')
session.find(:css, '#address1_city', visible: true)

expect(bridge).not_to have_received(:execute_atom)
end

it "won't use native displayed if told not to" do
skip 'Non-W3C uses native' if chrome?(session) && (ENV['W3C'] == 'false')

session.driver.options[:native_displayed] = false
session.visit('/form')
session.find(:css, '#address1_city', visible: true)

expect(bridge).to have_received(:execute_atom).with(:isDisplayed, any_args)
end
end
end

0 comments on commit 6d3fff1

Please sign in to comment.