XPath escape value in select/unselect under rack-test

This commit is contained in:
Jonas Nicklas 2010-04-26 17:23:34 +02:00
parent 32b3b6a796
commit cbb42a1da7
5 changed files with 31 additions and 14 deletions

View File

@ -29,7 +29,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
def set(value)
if tag_name == 'input' and type == 'radio'
driver.html.xpath("//input[@name='#{self[:name]}']").each { |node| node.remove_attribute("checked") }
driver.html.xpath("//input[@name=#{Capybara::XPath.escape(self[:name])}]").each { |node| node.remove_attribute("checked") }
node['checked'] = 'checked'
elsif tag_name == 'input' and type == 'checkbox'
if value
@ -49,8 +49,8 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
node.xpath(".//option[@selected]").each { |node| node.remove_attribute("selected") }
end
if option_node = node.xpath(".//option[text()='#{option}']").first ||
node.xpath(".//option[contains(.,'#{option}')]").first
if option_node = node.xpath(".//option[text()=#{Capybara::XPath.escape(option)}]").first ||
node.xpath(".//option[contains(.,#{Capybara::XPath.escape(option)})]").first
option_node["selected"] = 'selected'
else
options = node.xpath(".//option").map { |o| "'#{o.text}'" }.join(', ')
@ -63,8 +63,8 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
raise Capybara::UnselectNotAllowed, "Cannot unselect option '#{option}' from single select box."
end
if option_node = node.xpath(".//option[text()='#{option}']").first ||
node.xpath(".//option[contains(.,'#{option}')]").first
if option_node = node.xpath(".//option[text()=#{Capybara::XPath.escape(option)}]").first ||
node.xpath(".//option[contains(.,#{Capybara::XPath.escape(option)})]").first
option_node.remove_attribute('selected')
else
options = node.xpath(".//option").map { |o| "'#{o.text}'" }.join(', ')

View File

@ -31,6 +31,12 @@ shared_examples_for "select" do
extract_results(@session)['title'].should == 'Mr'
end
it "should escape quotes" do
@session.select("John's made-up language", :from => 'Locale')
@session.click_button('awesome')
extract_results(@session)['locale'].should == 'jo'
end
context "with a locator that doesn't exist" do
it "should raise an error" do
running { @session.select('foo', :from => 'does not exist') }.should raise_error(Capybara::ElementNotFound)

View File

@ -25,6 +25,12 @@ shared_examples_for "unselect" do
extract_results(@session)['underwear'].should include('Commando', 'Boxer Briefs')
extract_results(@session)['underwear'].should_not include('Briefs')
end
it "should escape quotes" do
@session.unselect("Frenchman's Pantalons", :from => 'Underwear')
@session.click_button('awesome')
extract_results(@session)['underwear'].should_not include("Frenchman's Pantalons")
end
end
context "with single select" do

View File

@ -76,6 +76,7 @@
<option selected="selected" value="en">English</option>
<option value="fi">Finish</option>
<option value="no">Norwegian</option>
<option value="jo">John's made-up language</option>
</select>
</p>
@ -142,6 +143,7 @@
<option>Boxers</option>
<option selected="selected">Briefs</option>
<option selected="selected">Commando</option>
<option selected="selected">Frenchman's Pantalons</option>
</select>
</p>

View File

@ -5,6 +5,17 @@ module Capybara
class XPath
class << self
def escape(string)
if string.include?("'")
string = string.split("'", -1).map do |substr|
"'#{substr}'"
end.join(%q{,"'",})
"concat(#{string})"
else
"'#{string}'"
end
end
def wrap(path)
if path.is_a?(self)
path
@ -161,15 +172,7 @@ module Capybara
# Sanitize a String for putting it into an xpath query
def s(string)
if string.include?("'")
string = string.split("'", -1).map do |substr|
"'#{substr}'"
end.join(%q{,"'",})
"concat(#{string})"
else
"'#{string}'"
end
XPath.escape(string)
end
end