mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
Allow check/uncheck/choose/attach_file/fill_in to work on element called on when no locator specified
This commit is contained in:
parent
fd5ef4fa03
commit
e5620e8ae2
9 changed files with 103 additions and 20 deletions
|
@ -62,6 +62,7 @@ module Capybara
|
|||
#
|
||||
# Locate a text field or text area and fill it in with the given text
|
||||
# The field can be found via its name, id, Capybara.test_id attribute, or label text.
|
||||
# If no locator is provided will operate on self or a descendant
|
||||
#
|
||||
# page.fill_in 'Name', with: 'Bob'
|
||||
#
|
||||
|
@ -82,6 +83,7 @@ module Capybara
|
|||
# @return [Capybara::Node::Element] The element filled_in
|
||||
def fill_in(locator = nil, with:, currently_with: nil, fill_options: {}, **find_options)
|
||||
find_options[:with] = currently_with if currently_with
|
||||
find_options[:allow_self] = true if locator.nil?
|
||||
find(:fillable_field, locator, find_options).set(with, fill_options)
|
||||
end
|
||||
|
||||
|
@ -90,8 +92,9 @@ module Capybara
|
|||
|
||||
##
|
||||
#
|
||||
# Find a radio button and mark it as checked. The radio button can be found
|
||||
# via name, id or label text.
|
||||
# Find a descendant radio button and mark it as checked. The radio button can be found
|
||||
# via name, id or label text. If no locator is provided this will match against self or
|
||||
# a descendant.
|
||||
#
|
||||
# page.choose('Male')
|
||||
#
|
||||
|
@ -112,8 +115,9 @@ module Capybara
|
|||
|
||||
##
|
||||
#
|
||||
# Find a check box and mark it as checked. The check box can be found
|
||||
# via name, id or label text.
|
||||
# Find a descendant check box and mark it as checked. The check box can be found
|
||||
# via name, id or label text. If no locator is provided this will match against
|
||||
# self or a descendant.
|
||||
#
|
||||
# page.check('German')
|
||||
#
|
||||
|
@ -135,8 +139,9 @@ module Capybara
|
|||
|
||||
##
|
||||
#
|
||||
# Find a check box and mark uncheck it. The check box can be found
|
||||
# via name, id or label text.
|
||||
# Find a descendant check box and mark uncheck it. The check box can be found
|
||||
# via name, id or label text. If no locator is provided this will match against
|
||||
# self or a descendant.
|
||||
#
|
||||
# page.uncheck('German')
|
||||
#
|
||||
|
@ -204,10 +209,11 @@ module Capybara
|
|||
|
||||
##
|
||||
#
|
||||
# Find a file field on the page and attach a file given its path. The file field can
|
||||
# Find a descendant file field on the page and attach a file given its path. The file field can
|
||||
# be found via its name, id or label text. In the case of the file field being hidden for
|
||||
# styling reasons the `make_visible` option can be used to temporarily change the CSS of
|
||||
# the file field, attach the file, and then revert the CSS back to original.
|
||||
# the file field, attach the file, and then revert the CSS back to original. If no locator is
|
||||
# passed this will match self or a descendant.
|
||||
#
|
||||
# page.attach_file(locator, '/path/to/file.png')
|
||||
#
|
||||
|
@ -230,6 +236,7 @@ module Capybara
|
|||
Array(paths).each do |path|
|
||||
raise Capybara::FileNotFound, "cannot attach file, #{path} does not exist" unless File.exist?(path.to_s)
|
||||
end
|
||||
options[:allow_self] = true if locator.nil?
|
||||
# Allow user to update the CSS style of the file input since they are so often hidden on a page
|
||||
if make_visible
|
||||
ff = find(:file_field, locator, options.merge(visible: :all))
|
||||
|
@ -291,6 +298,8 @@ module Capybara
|
|||
end
|
||||
|
||||
def _check_with_label(selector, checked, locator, allow_label_click: session_options.automatic_label_click, **options)
|
||||
options[:allow_self] = true if locator.nil?
|
||||
|
||||
synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do
|
||||
begin
|
||||
el = find(selector, locator, options)
|
||||
|
@ -299,7 +308,7 @@ module Capybara
|
|||
raise unless allow_label_click && catch_error?(err)
|
||||
begin
|
||||
el ||= find(selector, locator, options.merge(visible: :all))
|
||||
find(:label, for: el, visible: true).click unless el.checked? == checked
|
||||
el.session.find(:label, for: el, visible: true).click unless el.checked? == checked
|
||||
rescue StandardError # swallow extra errors - raise original
|
||||
raise err
|
||||
end
|
||||
|
|
|
@ -58,6 +58,7 @@ module Capybara
|
|||
end
|
||||
|
||||
def matches_filters?(node)
|
||||
return true if (@resolved_node&.== node) && options[:allow_self]
|
||||
@applied_filters ||= :system
|
||||
return false unless matches_text_filter?(node) && matches_exact_text_filter?(node) && matches_visible_filter?(node)
|
||||
@applied_filters = :node
|
||||
|
@ -210,7 +211,7 @@ module Capybara
|
|||
|
||||
return if unhandled_options.empty?
|
||||
invalid_names = unhandled_options.map(&:inspect).join(', ')
|
||||
valid_names = valid_keys.map(&:inspect).join(', ')
|
||||
valid_names = (valid_keys - [:allow_self]).map(&:inspect).join(', ')
|
||||
raise ArgumentError, "invalid keys #{invalid_names}, should be one of #{valid_names}"
|
||||
end
|
||||
|
||||
|
|
|
@ -194,8 +194,12 @@ end
|
|||
Capybara.add_selector(:fillable_field) do
|
||||
label 'field'
|
||||
|
||||
xpath do |locator, **options|
|
||||
xpath = XPath.descendant(:input, :textarea)[!XPath.attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file')]
|
||||
xpath(:allow_self) do |locator, **options|
|
||||
xpath = if options[:allow_self]
|
||||
XPath.descendant_or_self(:input, :textarea)
|
||||
else
|
||||
XPath.descendant(:input, :textarea)
|
||||
end[!XPath.attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file')]
|
||||
locate_field(xpath, locator, options)
|
||||
end
|
||||
|
||||
|
@ -223,8 +227,12 @@ end
|
|||
Capybara.add_selector(:radio_button) do
|
||||
label 'radio button'
|
||||
|
||||
xpath do |locator, **options|
|
||||
xpath = XPath.descendant(:input)[XPath.attr(:type) == 'radio']
|
||||
xpath(:allow_self) do |locator, **options|
|
||||
xpath = if options[:allow_self]
|
||||
XPath.descendant_or_self(:input)
|
||||
else
|
||||
XPath.descendant(:input)
|
||||
end[XPath.attr(:type) == 'radio']
|
||||
locate_field(xpath, locator, options)
|
||||
end
|
||||
|
||||
|
@ -239,8 +247,12 @@ Capybara.add_selector(:radio_button) do
|
|||
end
|
||||
|
||||
Capybara.add_selector(:checkbox) do
|
||||
xpath do |locator, **options|
|
||||
xpath = XPath.descendant(:input)[XPath.attr(:type) == 'checkbox']
|
||||
xpath(:allow_self) do |locator, **options|
|
||||
xpath = if options[:allow_self]
|
||||
XPath.descendant_or_self(:input)
|
||||
else
|
||||
XPath.descendant(:input)
|
||||
end[XPath.attr(:type) == 'checkbox']
|
||||
locate_field(xpath, locator, options)
|
||||
end
|
||||
|
||||
|
@ -375,8 +387,12 @@ end
|
|||
|
||||
Capybara.add_selector(:file_field) do
|
||||
label 'file field'
|
||||
xpath do |locator, options|
|
||||
xpath = XPath.descendant(:input)[XPath.attr(:type) == 'file']
|
||||
xpath(:allow_self) do |locator, options|
|
||||
xpath = if options[:allow_self]
|
||||
XPath.descendant_or_self(:input)
|
||||
else
|
||||
XPath.descendant(:input)
|
||||
end[XPath.attr(:type) == 'file']
|
||||
locate_field(xpath, locator, options)
|
||||
end
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class Capybara::Selenium::MarionetteNode < Capybara::Selenium::Node
|
|||
|
||||
def set_file(value) # rubocop:disable Naming/AccessorMethodName
|
||||
# By default files are appended so we have to clear here if its multiple and already set
|
||||
native.clear if multiple? && driver.evaluate_script("arguments[0].files", self).any?
|
||||
native.clear if multiple? && driver.evaluate_script('arguments[0].files', self).any?
|
||||
return super if browser_version >= 62.0
|
||||
|
||||
# Workaround lack of support for multiple upload by uploading one at a time
|
||||
|
|
|
@ -22,6 +22,13 @@ Capybara::SpecHelper.spec '#attach_file' do
|
|||
expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
|
||||
end
|
||||
|
||||
it 'should be able to set on element if no locator passed' do
|
||||
ff = @session.find(:file_field, 'Image')
|
||||
ff.attach_file(with_os_path_separators(__FILE__))
|
||||
@session.click_button('awesome')
|
||||
expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
|
||||
end
|
||||
|
||||
it 'casts to string' do
|
||||
@session.attach_file :form_image, with_os_path_separators(__FILE__)
|
||||
@session.click_button('awesome')
|
||||
|
|
|
@ -68,6 +68,13 @@ Capybara::SpecHelper.spec '#check' do
|
|||
expect(extract_results(@session)['pets']).to include('dog', 'cat', 'hamster')
|
||||
end
|
||||
|
||||
it 'should be able to check itself if no locator specified' do
|
||||
cb = @session.find(:id, 'form_pets_cat')
|
||||
cb.check
|
||||
@session.click_button('awesome')
|
||||
expect(extract_results(@session)['pets']).to include('dog', 'cat', 'hamster')
|
||||
end
|
||||
|
||||
it 'casts to string' do
|
||||
@session.check(:form_pets_cat)
|
||||
@session.click_button('awesome')
|
||||
|
@ -142,6 +149,20 @@ Capybara::SpecHelper.spec '#check' do
|
|||
expect(extract_results(@session)['cars']).to include('mclaren')
|
||||
end
|
||||
|
||||
it 'should check via clicking the label with :for attribute if locator nil' do
|
||||
cb = @session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)
|
||||
cb.check
|
||||
@session.click_button('awesome')
|
||||
expect(extract_results(@session)['cars']).to include('tesla')
|
||||
end
|
||||
|
||||
it 'should check self via clicking the wrapping label if locator nil' do
|
||||
cb = @session.find(:checkbox, 'form_cars_mclaren', unchecked: true, visible: :hidden)
|
||||
cb.check
|
||||
@session.click_button('awesome')
|
||||
expect(extract_results(@session)['cars']).to include('mclaren')
|
||||
end
|
||||
|
||||
it 'should not click the label if unneeded' do
|
||||
expect(@session.find(:checkbox, 'form_cars_jaguar', checked: true, visible: :hidden)).to be_truthy
|
||||
@session.check('form_cars_jaguar')
|
||||
|
|
|
@ -23,6 +23,13 @@ Capybara::SpecHelper.spec '#choose' do
|
|||
expect(extract_results(@session)['gender']).to eq('male')
|
||||
end
|
||||
|
||||
it 'should be able to choose self when no locator string specified' do
|
||||
rb = @session.find(:id, 'gender_male')
|
||||
rb.choose
|
||||
@session.click_button('awesome')
|
||||
expect(extract_results(@session)['gender']).to eq('male')
|
||||
end
|
||||
|
||||
it 'casts to string' do
|
||||
@session.choose('Both')
|
||||
@session.click_button(:awesome)
|
||||
|
@ -82,12 +89,19 @@ Capybara::SpecHelper.spec '#choose' do
|
|||
Capybara.automatic_label_click = old_click_label
|
||||
end
|
||||
|
||||
it 'should select by clicking the link if available' do
|
||||
it 'should select by clicking the label if available' do
|
||||
@session.choose('party_democrat')
|
||||
@session.click_button('awesome')
|
||||
expect(extract_results(@session)['party']).to eq('democrat')
|
||||
end
|
||||
|
||||
it 'should select self by clicking the label if no locator specified' do
|
||||
cb = @session.find(:id, 'party_democrat', visible: :hidden)
|
||||
cb.choose
|
||||
@session.click_button('awesome')
|
||||
expect(extract_results(@session)['party']).to eq('democrat')
|
||||
end
|
||||
|
||||
it 'should raise error if not allowed to click label' do
|
||||
expect { @session.choose('party_democrat', allow_label_click: false) }.to raise_error(Capybara::ElementNotFound, 'Unable to find visible radio button "party_democrat"')
|
||||
end
|
||||
|
|
|
@ -137,6 +137,13 @@ Capybara::SpecHelper.spec '#fill_in' do
|
|||
expect(extract_results(@session)['schmooo']).to eq('Schmooo for all')
|
||||
end
|
||||
|
||||
it 'should be able to fill in element called on when no locator passed' do
|
||||
field = @session.find(:fillable_field, 'form[password]')
|
||||
field.fill_in(with: 'supasikrit')
|
||||
@session.click_button('awesome')
|
||||
expect(extract_results(@session)['password']).to eq('supasikrit')
|
||||
end
|
||||
|
||||
it "should throw an exception if a hash containing 'with' is not provided" do
|
||||
expect { @session.fill_in 'Name' }.to raise_error(ArgumentError, /with/)
|
||||
end
|
||||
|
|
|
@ -26,6 +26,14 @@ Capybara::SpecHelper.spec '#uncheck' do
|
|||
expect(extract_results(@session)['pets']).not_to include('hamster')
|
||||
end
|
||||
|
||||
it 'should be able to uncheck itself if no locator specified' do
|
||||
cb = @session.find(:id, 'form_pets_hamster')
|
||||
cb.uncheck
|
||||
@session.click_button('awesome')
|
||||
expect(extract_results(@session)['pets']).to include('dog')
|
||||
expect(extract_results(@session)['pets']).not_to include('hamster')
|
||||
end
|
||||
|
||||
it 'casts to string' do
|
||||
@session.uncheck(:form_pets_hamster)
|
||||
@session.click_button('awesome')
|
||||
|
|
Loading…
Reference in a new issue