Declare `Session#send_keys` (#2422)

When covering hotkeys and tab-navigation with test coverage, sending
keys via particular elements (via `Node#send_keys`) can be tedious.

As an alternative, invoke `Session#send_keys` to delegate to the element
with current focus.

In Rack Test environments, `Session#send_keys` raises an error.
This commit is contained in:
Sean Doyle 2020-11-16 20:26:59 -05:00 committed by GitHub
parent 54b0081dfd
commit 8c4bffda86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 1 deletions

View File

@ -7,6 +7,12 @@ Release date: unreleased
* Current path assetsions/expectations accept optional filter block
* Animation disabler now specifies `scroll-behavior: auto;` [Nathan Broadbent]
* :button selector can now find elements by label text [Sean Doyle]
* In Selenium-enabled environments, `Session#send_keys` delegates to the current
element with focus (via [document.activeElement][]). When called from Rack
Test environments, `Session#send_keys` raises an error [Sean Doyle]
[document.activeElement]: https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement
[Sean Doyle]: https://github.com/seanpdoyle/
### Changed

View File

@ -59,6 +59,10 @@ class Capybara::Driver::Base
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#status_code'
end
def send_keys(*)
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#send_keys'
end
##
#
# @param frame [Capybara::Node::Element, :parent, :top] The iframe element to switch to

View File

@ -133,6 +133,10 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
unwrap_script_result(result)
end
def send_keys(*args)
active_element.send_keys(*args)
end
def save_screenshot(path, **_options)
browser.save_screenshot(path)
end
@ -455,6 +459,10 @@ 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

View File

@ -58,7 +58,7 @@ module Capybara
].freeze
SESSION_METHODS = %i[
body html source current_url current_host current_path
execute_script evaluate_script visit refresh go_back go_forward
execute_script evaluate_script visit refresh go_back go_forward send_keys
within within_element within_fieldset within_table within_frame switch_to_frame
current_window windows open_new_window switch_to_window within_window window_opened_by
save_page save_and_open_page save_screenshot
@ -303,6 +303,14 @@ module Capybara
driver.go_forward
end
##
# @!method send_keys
# @see Capybara::Node::Element#send_keys
#
def send_keys(*args, **kw_args)
driver.send_keys(*args, **kw_args)
end
##
#
# Executes the given block within the context of a node. {#within} takes the

View File

@ -145,6 +145,14 @@ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
end
end
describe '#send_keys' do
it 'raises an UnsupportedMethodError' do
session.visit('/form')
expect { session.send_keys(:tab) }.to raise_error(Capybara::NotSupportedByDriverError)
end
end
describe '#text' do
it 'should return original text content for textareas' do
session.visit('/with_html')

View File

@ -222,6 +222,18 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
end
end
describe '#send_keys' do
it 'defaults to sending keys to the document.activeElement' do
session.visit('/form')
expect(session.evaluate_script('document.activeElement')).to eq(session.find('//body'))
session.send_keys(:tab)
expect(session.evaluate_script('document.activeElement')).to eq(session.first(:field))
end
end
describe '#path' do
it 'returns xpath' do
# this is here because it is testing for an XPath that is specific to the algorithm used in the selenium driver