From 5c1d6d34f8e28d631d761f9c45f225426fa674d6 Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Sun, 31 Jan 2021 21:08:43 -0500 Subject: [PATCH] Support `Session#active_element` As a [follow-up][] to [#2422][], expose the [document.activeElement][] (that is, the element with focus) via the `Session`. When called from Rack Test environments, `Session#active_element` raises an error. [Document.activeElement]: https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement [follow-up]: https://github.com/teamcapybara/capybara/pull/2422#discussion_r520646573 [#2422]: https://github.com/teamcapybara/capybara/pull/2422 [document.activeElement]: https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement --- History.md | 1 + lib/capybara/driver/base.rb | 4 ++++ lib/capybara/selenium/driver.rb | 10 +++++----- lib/capybara/session.rb | 10 ++++++++++ lib/capybara/spec/session/active_element_spec.rb | 14 ++++++++++++++ spec/rack_test_spec.rb | 9 +++++++++ 6 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 lib/capybara/spec/session/active_element_spec.rb diff --git a/History.md b/History.md index b17aea59..b663f636 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,7 @@ Release date: unreleased * `allow_label_click` accepts click options to be used when clicking an associated label * Deprecated `allow_gumbo=` in favor of `use_html5_parsing=` to enable use of Nokogiri::HTL5 when available +* `Session#active_element` returns the element with focus - Not supported by the `RackTest` driver [Sean Doyle] ### Fixed diff --git a/lib/capybara/driver/base.rb b/lib/capybara/driver/base.rb index daf194c6..99746377 100644 --- a/lib/capybara/driver/base.rb +++ b/lib/capybara/driver/base.rb @@ -63,6 +63,10 @@ class Capybara::Driver::Base raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#send_keys' end + def active_element + raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#active_element' + end + ## # # @param frame [Capybara::Node::Element, :parent, :top] The iframe element to switch to diff --git a/lib/capybara/selenium/driver.rb b/lib/capybara/selenium/driver.rb index 16f8f116..9e62c7da 100644 --- a/lib/capybara/selenium/driver.rb +++ b/lib/capybara/selenium/driver.rb @@ -148,8 +148,12 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base unwrap_script_result(result) end + def active_element + build_node(browser.switch_to.active_element) + end + def send_keys(*args) - active_element.send_keys(*args) + active_element.native.send_keys(*args) end def save_screenshot(path, **_options) @@ -474,10 +478,6 @@ private browser end - def active_element - browser.switch_to.active_element - end - def build_node(native_node, initial_cache = {}) ::Capybara::Selenium::Node.new(self, native_node, initial_cache) end diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb index b95f96c6..a55e44d9 100644 --- a/lib/capybara/session.rb +++ b/lib/capybara/session.rb @@ -311,6 +311,16 @@ module Capybara driver.send_keys(*args, **kw_args) end + ## + # + # Returns the element with focus. + # + # Not supported by Rack Test + # + def active_element + driver.active_element + end + ## # # Executes the given block within the context of a node. {#within} takes the diff --git a/lib/capybara/spec/session/active_element_spec.rb b/lib/capybara/spec/session/active_element_spec.rb new file mode 100644 index 00000000..57502c53 --- /dev/null +++ b/lib/capybara/spec/session/active_element_spec.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +Capybara::SpecHelper.spec '#active_element', requires: [:js] do + it 'should return the active element' do + @session.visit('/form') + @session.send_keys(:tab) + + expect(@session.active_element).to eq(@session.find_by_id('form_title')) + + @session.send_keys(:tab) + + expect(@session.active_element).not_to eq(@session.find_by_id('form_title')) + end +end diff --git a/spec/rack_test_spec.rb b/spec/rack_test_spec.rb index 89cc5a62..0451eed4 100644 --- a/spec/rack_test_spec.rb +++ b/spec/rack_test_spec.rb @@ -12,6 +12,7 @@ skipped_tests = %i[ screenshot frames windows + active_element send_keys server hover @@ -147,6 +148,14 @@ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes end end + describe '#active_element' do + it 'raises an UnsupportedMethodError' do + session.visit('/form') + + expect { session.active_element }.to raise_error(Capybara::NotSupportedByDriverError) + end + end + describe '#text' do it 'should return original text content for textareas' do session.visit('/with_html')