mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
Merge branch 'css' of git://github.com/twalpole/capybara into twalpole-css
Conflicts: lib/capybara/query.rb
This commit is contained in:
commit
2380ba854c
17 changed files with 102 additions and 35 deletions
|
@ -327,6 +327,7 @@ module Capybara
|
|||
autoload :Node, 'capybara/rack_test/node'
|
||||
autoload :Form, 'capybara/rack_test/form'
|
||||
autoload :Browser, 'capybara/rack_test/browser'
|
||||
autoload :CSSHandlers, 'capybara/rack_test/css_handlers.rb'
|
||||
end
|
||||
|
||||
module Selenium
|
||||
|
|
|
@ -7,7 +7,11 @@ class Capybara::Driver::Base
|
|||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def find(query)
|
||||
def find_xpath(query)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def find_css(query)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
|
|
|
@ -145,7 +145,12 @@ module Capybara
|
|||
|
||||
def resolve_query(query, exact=nil)
|
||||
elements = synchronize do
|
||||
base.find(query.xpath(exact)).map do |node|
|
||||
# base.find(query.xpath(exact)).map do |node|
|
||||
if query.selector.format==:css
|
||||
base.find_css(query.css)
|
||||
else
|
||||
base.find_xpath(query.xpath(exact))
|
||||
end.map do |node|
|
||||
Capybara::Node::Element.new(session, node, self, query)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -154,7 +154,11 @@ module Capybara
|
|||
private
|
||||
|
||||
def resolve_query(query, exact=nil)
|
||||
elements = native.xpath(query.xpath(exact)).map do |node|
|
||||
elements = if query.selector.format == :css
|
||||
native.css(query.css)
|
||||
else
|
||||
native.xpath(query.xpath(exact))
|
||||
end.map do |node|
|
||||
self.class.new(node)
|
||||
end
|
||||
Capybara::Result.new(elements, query)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module Capybara
|
||||
class Query
|
||||
attr_accessor :selector, :locator, :options, :xpath, :find, :negative
|
||||
attr_accessor :selector, :locator, :options, :expression, :find, :negative
|
||||
|
||||
VALID_KEYS = [:text, :visible, :between, :count, :maximum, :minimum, :exact, :match]
|
||||
|
||||
|
@ -21,7 +21,7 @@ module Capybara
|
|||
@options[:exact] = true
|
||||
end
|
||||
|
||||
@xpath = @selector.call(@locator)
|
||||
@expression = @selector.call(@locator)
|
||||
assert_valid_keys!
|
||||
end
|
||||
|
||||
|
@ -90,14 +90,17 @@ module Capybara
|
|||
|
||||
def xpath(exact=nil)
|
||||
exact = self.exact? if exact == nil
|
||||
|
||||
if @xpath.respond_to?(:to_xpath) and exact
|
||||
@xpath.to_xpath(:exact)
|
||||
if @expression.respond_to?(:to_xpath) and exact
|
||||
@expression.to_xpath(:exact)
|
||||
else
|
||||
@xpath.to_s
|
||||
@expression.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def css
|
||||
@expression
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def assert_valid_keys!
|
||||
|
|
|
@ -80,8 +80,12 @@ class Capybara::RackTest::Browser
|
|||
@dom ||= Nokogiri::HTML(html)
|
||||
end
|
||||
|
||||
def find(selector)
|
||||
dom.xpath(selector).map { |node| Capybara::RackTest::Node.new(self, node) }
|
||||
def find(format, selector)
|
||||
if format==:css
|
||||
dom.css(selector, Capybara::RackTest::CSSHandlers.new)
|
||||
else
|
||||
dom.xpath(selector)
|
||||
end.map { |node| Capybara::RackTest::Node.new(self, node) }
|
||||
end
|
||||
|
||||
def html
|
||||
|
|
8
lib/capybara/rack_test/css_handlers.rb
Normal file
8
lib/capybara/rack_test/css_handlers.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
class Capybara::RackTest::CSSHandlers
|
||||
def disabled list
|
||||
list.find_all { |node| node.has_attribute? 'disabled' }
|
||||
end
|
||||
def enabled list
|
||||
list.find_all { |node| !node.has_attribute? 'disabled' }
|
||||
end
|
||||
end
|
|
@ -62,8 +62,12 @@ class Capybara::RackTest::Driver < Capybara::Driver::Base
|
|||
response.status
|
||||
end
|
||||
|
||||
def find(selector)
|
||||
browser.find(selector)
|
||||
def find_xpath(selector)
|
||||
browser.find(:xpath, selector)
|
||||
end
|
||||
|
||||
def find_css(selector)
|
||||
browser.find(:css,selector)
|
||||
end
|
||||
|
||||
def html
|
||||
|
|
|
@ -33,7 +33,7 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|||
|
||||
def select_option
|
||||
if select_node['multiple'] != 'multiple'
|
||||
select_node.find(".//option[@selected]").each { |node| node.native.remove_attribute("selected") }
|
||||
select_node.find_xpath(".//option[@selected]").each { |node| node.native.remove_attribute("selected") }
|
||||
end
|
||||
native["selected"] = 'selected'
|
||||
end
|
||||
|
@ -80,10 +80,14 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|||
native.path
|
||||
end
|
||||
|
||||
def find(locator)
|
||||
def find_xpath(locator)
|
||||
native.xpath(locator).map { |n| self.class.new(driver, n) }
|
||||
end
|
||||
|
||||
def find_css(locator)
|
||||
native.css(locator, Capybara::RackTest::CSSHandlers.new).map { |n| self.class.new(driver, n) }
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
native == other.native
|
||||
end
|
||||
|
@ -112,7 +116,7 @@ private
|
|||
|
||||
# a reference to the select node if this is an option node
|
||||
def select_node
|
||||
find('./ancestor::select').first
|
||||
find_xpath('./ancestor::select').first
|
||||
end
|
||||
|
||||
def type
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module Capybara
|
||||
class Selector
|
||||
attr_reader :name, :custom_filters
|
||||
attr_reader :name, :custom_filters, :format
|
||||
|
||||
|
||||
class << self
|
||||
|
@ -27,16 +27,16 @@ module Capybara
|
|||
end
|
||||
|
||||
def xpath(&block)
|
||||
@format = :xpath
|
||||
@xpath = block if block
|
||||
@xpath
|
||||
end
|
||||
|
||||
# Same as xpath, but wrap in XPath.css().
|
||||
def css(&block)
|
||||
if block
|
||||
@xpath = xpath { |*args| XPath.css(block.call(*args)) }
|
||||
end
|
||||
@xpath
|
||||
@format = :css
|
||||
@css = block if block
|
||||
@css
|
||||
end
|
||||
|
||||
def match(&block)
|
||||
|
@ -50,8 +50,12 @@ module Capybara
|
|||
end
|
||||
|
||||
def call(locator)
|
||||
if @format==:css
|
||||
@css.call(locator)
|
||||
else
|
||||
@xpath.call(locator)
|
||||
end
|
||||
end
|
||||
|
||||
def match?(locator)
|
||||
@match and @match.call(locator)
|
||||
|
|
|
@ -46,10 +46,14 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|||
browser.current_url
|
||||
end
|
||||
|
||||
def find(selector)
|
||||
def find_xpath(selector)
|
||||
browser.find_elements(:xpath, selector).map { |node| Capybara::Selenium::Node.new(self, node) }
|
||||
end
|
||||
|
||||
def find_css(selector)
|
||||
browser.find_elements(:css, selector).map { |node| Capybara::Selenium::Node.new(self, node) }
|
||||
end
|
||||
|
||||
def wait?; true; end
|
||||
def needs_server?; true; end
|
||||
|
||||
|
@ -127,4 +131,5 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|||
def invalid_element_errors
|
||||
[Selenium::WebDriver::Error::StaleElementReferenceError, Selenium::WebDriver::Error::UnhandledError, Selenium::WebDriver::Error::ElementNotVisibleError]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -81,10 +81,14 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|||
|
||||
alias :checked? :selected?
|
||||
|
||||
def find(locator)
|
||||
def find_xpath(locator)
|
||||
native.find_elements(:xpath, locator).map { |n| self.class.new(driver, n) }
|
||||
end
|
||||
|
||||
def find_css(locator)
|
||||
native.find_elements(:css, locator).map { |n| self.class.new(driver, n) }
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
native == other.native
|
||||
end
|
||||
|
@ -93,6 +97,6 @@ private
|
|||
|
||||
# a reference to the select node if this is an option node
|
||||
def select_node
|
||||
find('./ancestor::select').first
|
||||
find_xpath('./ancestor::select').first
|
||||
end
|
||||
end
|
||||
|
|
|
@ -41,6 +41,10 @@ Capybara::SpecHelper.spec '#find' do
|
|||
@session.find(:css, 'h1').text.should == 'This is a test'
|
||||
@session.find(:css, "input[id='test_field']")[:value].should == 'monkey'
|
||||
end
|
||||
|
||||
it "should support pseudo selectors" do
|
||||
@session.find(:css, 'input:disabled').value.should == 'This is disabled'
|
||||
end
|
||||
end
|
||||
|
||||
context "with xpath selectors" do
|
||||
|
@ -296,5 +300,11 @@ Capybara::SpecHelper.spec '#find' do
|
|||
@session.find('.//li[1]').text.should =~ /With Simple HTML/
|
||||
end
|
||||
end
|
||||
|
||||
it "should support pseudo selectors" do
|
||||
@session.within(:xpath, "//div[@id='for_bar']") do
|
||||
@session.find(:css, 'input:disabled').value.should == 'James'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ Capybara::SpecHelper.spec '#within' do
|
|||
|
||||
context "with CSS selector" do
|
||||
it "should click links in the given scope" do
|
||||
@session.within(:css, "#for_bar li[contains('With Simple HTML')]") do
|
||||
@session.within(:css, "#for_bar li", text: 'With Simple HTML') do
|
||||
@session.click_link('Go')
|
||||
end
|
||||
@session.should have_content('Bar')
|
||||
|
@ -46,7 +46,7 @@ Capybara::SpecHelper.spec '#within' do
|
|||
|
||||
context "with Node rather than selector" do
|
||||
it "should click links in the given scope" do
|
||||
node_of_interest = @session.find(:css, "#for_bar li[contains('With Simple HTML')]")
|
||||
node_of_interest = @session.find(:css, "#for_bar li", text: 'With Simple HTML')
|
||||
|
||||
@session.within(node_of_interest) do
|
||||
@session.click_link('Go')
|
||||
|
@ -58,7 +58,7 @@ Capybara::SpecHelper.spec '#within' do
|
|||
context "with the default selector set to CSS" do
|
||||
before { Capybara.default_selector = :css }
|
||||
it "should use CSS" do
|
||||
@session.within("#for_bar li[contains('With Simple HTML')]") do
|
||||
@session.within("#for_bar li", text: 'With Simple HTML') do
|
||||
@session.click_link('Go')
|
||||
end
|
||||
@session.should have_content('Bar')
|
||||
|
|
|
@ -93,3 +93,5 @@ banana</textarea>
|
|||
<div class="almost_singular but_not_quite">almost singular but not quite</div>
|
||||
<div class="almost_singular">almost singular</div>
|
||||
</div>
|
||||
|
||||
<input type="text" disabled name="disabled_text" value="This is disabled"/>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
|
||||
incididunt ut labore et dolore magna aliqua. Ut enim ad minim venia.
|
||||
<a href="/redirect">Go</a>
|
||||
<input name="disabled" disabled/>
|
||||
</p>
|
||||
|
||||
<div id="for_bar">
|
||||
|
@ -23,6 +24,10 @@
|
|||
<label for="bar_first_name">First Name</label>
|
||||
<input type="text" name="form[first_name]" value="Peter" id="bar_first_name"/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="bar_other_name">Other Name</label>
|
||||
<input type="text" name="form[other_name]" value="James" id="bar_other_name" disabled/>
|
||||
</p>
|
||||
<p><input type="submit" value="Go"/></p>
|
||||
</form>
|
||||
</li>
|
||||
|
|
|
@ -84,14 +84,14 @@ describe Capybara::RackTest::Driver do
|
|||
it 'should keep headers on link clicks' do
|
||||
@driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
|
||||
@driver.visit('/header_links')
|
||||
@driver.find('.//a').first.click
|
||||
@driver.find_xpath('.//a').first.click
|
||||
@driver.html.should include('foobar')
|
||||
end
|
||||
|
||||
it 'should keep headers on form submit' do
|
||||
@driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
|
||||
@driver.visit('/header_links')
|
||||
@driver.find('.//input').first.click
|
||||
@driver.find_xpath('.//input').first.click
|
||||
@driver.html.should include('foobar')
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue