Merge pull request #1732 from jnicklas/aria_label

Add support for aria-label attribute in finders - Issue #1528
This commit is contained in:
Thomas Walpole 2016-08-15 11:33:12 -07:00 committed by GitHub
commit 22dfca46b8
9 changed files with 75 additions and 18 deletions

View File

@ -7,6 +7,7 @@ Release date: Unreleased
in rubies that support Exception#cause rather than a confusing ExpectationNotMet - Issue #1719 [Thomas Walpole]
* background/given/given! RSoec aliases will work if RSpec config.shared_context_metadata_behavior == :apply_to_host_groups [Thomas Walpole]
* Fixed setting of unexpectedAlertError now that Selenium will be freezing the Capabilities::DEFAULTS [Thomas Walpole]
### Added
* 'check', 'uncheck', and 'choose' can now optionally click the associated label if the checkbox/radio button is not visible [Thomas Walpole]
* Raise error if Capybara.app_host/default_host are specified incorrectly [Thomas Walpole]
@ -15,7 +16,8 @@ Release date: Unreleased
* New frames API for drivers - Issue #1365 [Thomas Walpole]
* Deprecated Element#parent in favor of Element#query_scope to better indicate what it is [Thomas Walpole]
* Improved error messages for have_text matcher [Alex Chaffee, Thomas Walpole]
* The `:with` option for the field selector now accepts a regular expression for matching the field value[Uwe Kubosch]
* The `:with` option for the field selector now accepts a regular expression for matching the field value [Uwe Kubosch]
* Support matching on aria-label attribute when finding fields/links/buttons - Issue #1528 [Thomas Walpole]
#Version 2.7.1
Release date: 2016-05-01

View File

@ -22,7 +22,7 @@ module Capybara
class << self
attr_reader :app_host, :default_host
attr_accessor :asset_host, :run_server, :always_include_port
attr_accessor :server_port, :exact, :match, :exact_options, :visible_text_only
attr_accessor :server_port, :exact, :match, :exact_options, :visible_text_only, :enable_aria_label
attr_accessor :default_selector, :default_max_wait_time, :ignore_hidden_elements
attr_accessor :save_path, :wait_on_first_by_default, :automatic_label_click, :automatic_reload
attr_accessor :reuse_server, :raise_server_errors, :server_errors
@ -54,6 +54,7 @@ module Capybara
# [save_path = String] Where to put pages saved through save_(page|screenshot), save_and_open_(page|screenshot) (Default: Dir.pwd)
# [wait_on_first_by_default = Boolean] Whether Node#first defaults to Capybara waiting behavior for at least 1 element to match (Default: false)
# [automatic_label_click = Boolean] Whether Node#choose, Node#check, Node#uncheck will attempt to click the associated label element if the checkbox/radio button are non-visible (Default: false)
# [enable_aria_label = Boolean] Whether fields, links, and buttons will match against aria-label attribute (Default: false)
# [reuse_server = Boolean] Reuse the server thread between multiple sessions using the same app object (Default: true)
# === DSL Options
#
@ -500,6 +501,7 @@ Capybara.configure do |config|
config.visible_text_only = false
config.wait_on_first_by_default = false
config.automatic_label_click = false
config.enable_aria_label = false
config.reuse_server = true
end

View File

@ -95,10 +95,13 @@ module Capybara
private
def locate_field(xpath, locator)
locate_field = xpath[XPath.attr(:id).equals(locator) |
XPath.attr(:name).equals(locator) |
XPath.attr(:placeholder).equals(locator) |
XPath.attr(:id).equals(XPath.anywhere(:label)[XPath.string.n.is(locator)].attr(:for))]
attr_matchers = XPath.attr(:id).equals(locator) |
XPath.attr(:name).equals(locator) |
XPath.attr(:placeholder).equals(locator) |
XPath.attr(:id).equals(XPath.anywhere(:label)[XPath.string.n.is(locator)].attr(:for))
attr_matchers |= XPath.attr(:'aria-label').is(locator) if Capybara.enable_aria_label
locate_field = xpath[attr_matchers]
locate_field += XPath.descendant(:label)[XPath.string.n.is(locator)].descendant(xpath)
locate_field
end
@ -182,10 +185,12 @@ Capybara.add_selector(:link) do
xpath = XPath.descendant(:a)[XPath.attr(:href)]
unless locator.nil?
locator = locator.to_s
xpath = xpath[XPath.attr(:id).equals(locator) |
XPath.string.n.is(locator) |
XPath.attr(:title).is(locator) |
XPath.descendant(:img)[XPath.attr(:alt).is(locator)]]
matchers = XPath.attr(:id).equals(locator) |
XPath.string.n.is(locator) |
XPath.attr(:title).is(locator) |
XPath.descendant(:img)[XPath.attr(:alt).is(locator)]
matchers |= XPath.attr(:'aria-label').is(locator) if Capybara.enable_aria_label
xpath = xpath[matchers]
end
xpath
end
@ -209,9 +214,16 @@ Capybara.add_selector(:button) do
unless locator.nil?
locator = locator.to_s
input_btn_xpath = input_btn_xpath[XPath.attr(:id).equals(locator) | XPath.attr(:value).is(locator) | XPath.attr(:title).is(locator)]
btn_xpath = btn_xpath[XPath.attr(:id).equals(locator) | XPath.attr(:value).is(locator) | XPath.string.n.is(locator) | XPath.attr(:title).is(locator)]
image_btn_xpath = image_btn_xpath[XPath.attr(:alt).is(locator)]
locator_matches = XPath.attr(:id).equals(locator) | XPath.attr(:value).is(locator) | XPath.attr(:title).is(locator)
locator_matches |= XPath.attr(:'aria-label').is(locator) if Capybara.enable_aria_label
input_btn_xpath = input_btn_xpath[locator_matches]
btn_xpath = btn_xpath[locator_matches | XPath.string.n.is(locator)]
alt_matches = XPath.attr(:alt).is(locator)
alt_matches |= XPath.attr(:'aria-label').is(locator) if Capybara.enable_aria_label
image_btn_xpath = image_btn_xpath[alt_matches]
end
input_btn_xpath + btn_xpath + image_btn_xpath

View File

@ -9,6 +9,18 @@ Capybara::SpecHelper.spec '#find_button' do
expect(@session.find_button('crap321').value).to eq("crappy")
end
context "aria_label attribute with Capybara.enable_aria_label" do
it "should find when true" do
Capybara.enable_aria_label = true
expect(@session.find_button('Mediocre Button')[:id]).to eq("mediocre")
end
it "should not find when false" do
Capybara.enable_aria_label = false
expect { @session.find_button('Mediocre Button') }.to raise_error(Capybara::ElementNotFound)
end
end
it "casts to string" do
expect(@session.find_button(:'med')[:id]).to eq("mediocre")
end

View File

@ -8,6 +8,21 @@ Capybara::SpecHelper.spec '#find_field' do
expect(@session.find_field('Dog').value).to eq('dog')
expect(@session.find_field('form_description').text).to eq('Descriptive text goes here')
expect(@session.find_field('Region')[:name]).to eq('form[region]')
end
context "aria_label attribute with Capybara.enable_aria_label" do
it "should find when true" do
Capybara.enable_aria_label = true
expect(@session.find_field('Unlabelled Input')[:name]).to eq('form[which_form]')
# expect(@session.find_field('Emergency Number')[:id]).to eq('html5_tel')
end
it "should not find when false" do
Capybara.enable_aria_label = false
expect { @session.find_field('Unlabelled Input') }.to raise_error(Capybara::ElementNotFound)
# expect { @session.find_field('Emergency Number') }.to raise_error(Capybara::ElementNotFound)
end
end
it "casts to string" do

View File

@ -4,11 +4,23 @@ Capybara::SpecHelper.spec '#find_link' do
@session.visit('/with_html')
end
it "should find any field" do
it "should find any link" do
expect(@session.find_link('foo').text).to eq("ullamco")
expect(@session.find_link('labore')[:href]).to match %r(/with_simple_html$)
end
context "aria_label attribute with Capybara.enable_aria_label" do
it "should find when true" do
Capybara.enable_aria_label = true
expect(@session.find_link('Go to simple')[:href]).to match %r(/with_simple_html$)
end
it "should not find when false" do
Capybara.enable_aria_label = false
expect { @session.find_link('Go to simple') }.to raise_error(Capybara::ElementNotFound)
end
end
it "casts to string" do
expect(@session.find_link(:'foo').text).to eq("ullamco")
end

View File

@ -38,6 +38,7 @@ module Capybara
Capybara.visible_text_only = false
Capybara.match = :smart
Capybara.wait_on_first_by_default = false
Capybara.enable_aria_label = false
end
def filter(requires, metadata)

View File

@ -397,7 +397,7 @@ New line after and before textarea tag
</p>
<p>
<input type="submit" name="form[mediocre]" id="mediocre" value="med"/>
<input type="submit" name="form[mediocre]" id="mediocre" value="med" aria-label="Mediocre Button"/>
<p>
</form>
@ -482,9 +482,10 @@ New line after and before textarea tag
<label for="html5_search">Html5 Search</label>
<input type="search" name="form[html5_search]" value="what are you looking for" id="html5_search"/>
</p>
<p id="emergency">Emergency Number</p>
<p>
<label for="html5_tel">Html5 Tel</label>
<input type="tel" name="form[html5_tel]" value="911" id="html5_tel"/>
<input type="tel" aria-labelledby="emergency" name="form[html5_tel]" value="911" id="html5_tel"/>
</p>
<p>
<label for="html5_color">Html5 Color</label>
@ -507,7 +508,7 @@ New line after and before textarea tag
<form action="/other_form" method="post">
<p>
<input type="text" name="form[which_form]" value="formaction form"/>
<input type="text" name="form[which_form]" value="formaction form" aria-label="Unlabelled Input"/>
</p>
<input type="submit" name="form[button]" formaction="/form" value="Formaction button"/>
<input type="submit" name="form[button]" formaction="/form/get" formmethod="get" value="Formmethod button"/>

View File

@ -19,7 +19,7 @@
et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation <a href="/foo" id="foo">ullamco</a> laboris nisi
ut aliquip ex ea commodo consequat.
<a href="/with_simple_html"><img width="20" height="20" alt="awesome image" /></a>
<a href="/with_simple_html" aria-label="Go to simple"><img width="20" height="20" alt="awesome image" /></a>
</p>
<p class="para" id="second">