diff --git a/Gemfile.lock b/Gemfile.lock index ed2632ef..89acb5a5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: git://github.com/jnicklas/xpath.git - revision: 07cbb7a + revision: 18be9a2 specs: xpath (0.0.1) diff --git a/lib/capybara.rb b/lib/capybara.rb index f0d1b867..1265a22d 100644 --- a/lib/capybara.rb +++ b/lib/capybara.rb @@ -1,5 +1,6 @@ require 'timeout' require 'nokogiri' +require 'xpath' module Capybara class CapybaraError < StandardError; end @@ -49,7 +50,6 @@ module Capybara autoload :Server, 'capybara/server' autoload :Session, 'capybara/session' - autoload :XPath, 'capybara/xpath' autoload :Node, 'capybara/node' autoload :Document, 'capybara/node' autoload :Element, 'capybara/node' diff --git a/lib/capybara/driver/rack_test_driver.rb b/lib/capybara/driver/rack_test_driver.rb index 86328e6f..4ed5b7d0 100644 --- a/lib/capybara/driver/rack_test_driver.rb +++ b/lib/capybara/driver/rack_test_driver.rb @@ -36,7 +36,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base def set(value) if tag_name == 'input' and type == 'radio' - other_radios_xpath = ::XPath.generate { |x| x.anywhere(:input)[x.attr(:name).equals(self[:name])] }.to_s + other_radios_xpath = XPath.generate { |x| x.anywhere(:input)[x.attr(:name).equals(self[:name])] }.to_s driver.html.xpath(other_radios_xpath).each { |node| node.remove_attribute("checked") } native['checked'] = 'checked' elsif tag_name == 'input' and type == 'checkbox' diff --git a/lib/capybara/node/actions.rb b/lib/capybara/node/actions.rb index 4d2826cd..f89b43be 100644 --- a/lib/capybara/node/actions.rb +++ b/lib/capybara/node/actions.rb @@ -11,7 +11,7 @@ module Capybara # def click_link_or_button(locator) msg = "no link or button '#{locator}' found" - find(:xpath, Capybara::XPath.link_or_button(locator), :message => msg).click + find(:xpath, XPath::HTML.link_or_button(locator), :message => msg).click end ## @@ -23,7 +23,7 @@ module Capybara # def click_link(locator) msg = "no link with title, id or text '#{locator}' found" - find(:xpath, Capybara::XPath.link(locator), :message => msg).click + find(:xpath, XPath::HTML.link(locator), :message => msg).click end ## @@ -34,7 +34,7 @@ module Capybara # def click_button(locator) msg = "no button with value or id or text '#{locator}' found" - find(:xpath, Capybara::XPath.button(locator), :message => msg).click + find(:xpath, XPath::HTML.button(locator), :message => msg).click end ## @@ -50,7 +50,7 @@ module Capybara def fill_in(locator, options={}) msg = "cannot fill in, no text field, text area or password field with id, name, or label '#{locator}' found" raise "Must pass a hash containing 'with'" if not options.is_a?(Hash) or not options.has_key?(:with) - find(:xpath, Capybara::XPath.fillable_field(locator), :message => msg).set(options[:with]) + find(:xpath, XPath::HTML.fillable_field(locator), :message => msg).set(options[:with]) end ## @@ -64,7 +64,7 @@ module Capybara # def choose(locator) msg = "cannot choose field, no radio button with id, name, or label '#{locator}' found" - find(:xpath, Capybara::XPath.radio_button(locator), :message => msg).set(true) + find(:xpath, XPath::HTML.radio_button(locator), :message => msg).set(true) end ## @@ -78,7 +78,7 @@ module Capybara # def check(locator) msg = "cannot check field, no checkbox with id, name, or label '#{locator}' found" - find(:xpath, Capybara::XPath.checkbox(locator), :message => msg).set(true) + find(:xpath, XPath::HTML.checkbox(locator), :message => msg).set(true) end ## @@ -92,7 +92,7 @@ module Capybara # def uncheck(locator) msg = "cannot uncheck field, no checkbox with id, name, or label '#{locator}' found" - find(:xpath, Capybara::XPath.checkbox(locator), :message => msg).set(false) + find(:xpath, XPath::HTML.checkbox(locator), :message => msg).set(false) end ## @@ -108,8 +108,8 @@ module Capybara def select(value, options={}) no_select_msg = "cannot select option, no select box with id, name, or label '#{options[:from]}' found" no_option_msg = "cannot select option, no option with text '#{value}' in select box '#{options[:from]}'" - select = find(:xpath, Capybara::XPath.select(options[:from]), :message => no_select_msg) - select.find(:xpath, Capybara::XPath.option(value), :message => no_option_msg).select_option + select = find(:xpath, XPath::HTML.select(options[:from]), :message => no_select_msg) + select.find(:xpath, XPath::HTML.option(value), :message => no_option_msg).select_option end ## @@ -125,8 +125,8 @@ module Capybara def unselect(value, options={}) no_select_msg = "cannot unselect option, no select box with id, name, or label '#{options[:from]}' found" no_option_msg = "cannot unselect option, no option with text '#{value}' in select box '#{options[:from]}'" - select = find(:xpath, Capybara::XPath.select(options[:from]), :message => no_select_msg) - select.find(:xpath, Capybara::XPath.option(value), :message => no_option_msg).unselect_option + select = find(:xpath, XPath::HTML.select(options[:from]), :message => no_select_msg) + select.find(:xpath, XPath::HTML.option(value), :message => no_option_msg).unselect_option end ## @@ -141,7 +141,7 @@ module Capybara # def attach_file(locator, path) msg = "cannot attach file, no file field with id, name, or label '#{locator}' found" - find(:xpath, Capybara::XPath.file_field(locator), :message => msg).set(path) + find(:xpath, XPath::HTML.file_field(locator), :message => msg).set(path) end ## diff --git a/lib/capybara/node/finders.rb b/lib/capybara/node/finders.rb index 8ae01973..fb81446d 100644 --- a/lib/capybara/node/finders.rb +++ b/lib/capybara/node/finders.rb @@ -47,7 +47,7 @@ module Capybara # @return [Capybara::Element] The found element # def find_field(locator) - find(:xpath, Capybara::XPath.field(locator)) + find(:xpath, XPath::HTML.field(locator)) end alias_method :field_labeled, :find_field @@ -59,7 +59,7 @@ module Capybara # @return [Capybara::Element] The found element # def find_link(locator) - find(:xpath, Capybara::XPath.link(locator)) + find(:xpath, XPath::HTML.link(locator)) end ## @@ -70,7 +70,7 @@ module Capybara # @return [Capybara::Element] The found element # def find_button(locator) - find(:xpath, Capybara::XPath.button(locator)) + find(:xpath, XPath::HTML.button(locator)) end ## @@ -121,7 +121,7 @@ module Capybara def all(*args) options = if args.last.is_a?(Hash) then args.pop else {} end - results = Capybara::XPath.wrap(normalize_locator(*args)).map do |path| + results = XPath::HTML.wrap(normalize_locator(*args)).map do |path| base.find(path) end.flatten @@ -142,7 +142,7 @@ module Capybara def normalize_locator(kind, locator=nil) kind, locator = Capybara.default_selector, kind if locator.nil? - locator = Capybara::XPath.from_css(locator) if kind == :css + locator = XPath::HTML.from_css(locator) if kind == :css locator end diff --git a/lib/capybara/node/matchers.rb b/lib/capybara/node/matchers.rb index 06230bd1..25fb981c 100644 --- a/lib/capybara/node/matchers.rb +++ b/lib/capybara/node/matchers.rb @@ -30,67 +30,67 @@ module Capybara end def has_css?(path, options={}) - has_xpath?(Capybara::XPath.from_css(path), options) + has_xpath?(XPath::HTML.from_css(path), options) end def has_no_css?(path, options={}) - has_no_xpath?(Capybara::XPath.from_css(path), options) + has_no_xpath?(XPath::HTML.from_css(path), options) end def has_content?(content) - has_xpath?(Capybara::XPath.content(content)) + has_xpath?(XPath::HTML.content(content)) end def has_no_content?(content) - has_no_xpath?(Capybara::XPath.content(content)) + has_no_xpath?(XPath::HTML.content(content)) end def has_link?(locator) - has_xpath?(Capybara::XPath.link(locator)) + has_xpath?(XPath::HTML.link(locator)) end def has_no_link?(locator) - has_no_xpath?(Capybara::XPath.link(locator)) + has_no_xpath?(XPath::HTML.link(locator)) end def has_button?(locator) - has_xpath?(Capybara::XPath.button(locator)) + has_xpath?(XPath::HTML.button(locator)) end def has_no_button?(locator) - has_no_xpath?(Capybara::XPath.button(locator)) + has_no_xpath?(XPath::HTML.button(locator)) end def has_field?(locator, options={}) - has_xpath?(Capybara::XPath.field(locator, options)) + has_xpath?(XPath::HTML.field(locator, options)) end def has_no_field?(locator, options={}) - has_no_xpath?(Capybara::XPath.field(locator, options)) + has_no_xpath?(XPath::HTML.field(locator, options)) end def has_checked_field?(locator) - has_xpath?(Capybara::XPath.field(locator, :checked => true)) + has_xpath?(XPath::HTML.field(locator, :checked => true)) end def has_unchecked_field?(locator) - has_xpath?(Capybara::XPath.field(locator, :unchecked => true)) + has_xpath?(XPath::HTML.field(locator, :unchecked => true)) end def has_select?(locator, options={}) - has_xpath?(Capybara::XPath.select(locator, options)) + has_xpath?(XPath::HTML.select(locator, options)) end def has_no_select?(locator, options={}) - has_no_xpath?(Capybara::XPath.select(locator, options)) + has_no_xpath?(XPath::HTML.select(locator, options)) end def has_table?(locator, options={}) - has_xpath?(Capybara::XPath.table(locator, options)) + has_xpath?(XPath::HTML.table(locator, options)) end def has_no_table?(locator, options={}) - has_no_xpath?(Capybara::XPath.table(locator, options)) + has_no_xpath?(XPath::HTML.table(locator, options)) end end end diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb index fb441b58..f150a5c7 100644 --- a/lib/capybara/session.rb +++ b/lib/capybara/session.rb @@ -170,7 +170,7 @@ module Capybara # @param [String] locator Id or legend of the fieldset # def within_fieldset(locator) - within :xpath, Capybara::XPath.fieldset(locator) do + within :xpath, XPath::HTML.fieldset(locator) do yield end end @@ -182,7 +182,7 @@ module Capybara # @param [String] locator Id or caption of the table # def within_table(locator) - within :xpath, Capybara::XPath.table(locator) do + within :xpath, XPath::HTML.table(locator) do yield end end diff --git a/lib/capybara/spec/session/all_spec.rb b/lib/capybara/spec/session/all_spec.rb index a59f2e6d..0ac08e4d 100644 --- a/lib/capybara/spec/session/all_spec.rb +++ b/lib/capybara/spec/session/all_spec.rb @@ -16,7 +16,7 @@ shared_examples_for "all" do it "should accept an XPath instance" do @session.visit('/form') - @xpath = Capybara::XPath.fillable_field('Name') + @xpath = XPath::HTML.fillable_field('Name') @result = @session.all(@xpath).map { |r| r.value } @result.should include('Smith', 'John', 'John Smith') end diff --git a/lib/capybara/spec/session/find_spec.rb b/lib/capybara/spec/session/find_spec.rb index 59216ecd..b4f5db5d 100644 --- a/lib/capybara/spec/session/find_spec.rb +++ b/lib/capybara/spec/session/find_spec.rb @@ -72,7 +72,7 @@ shared_examples_for "find" do it "should accept an XPath instance and respect the order of paths" do @session.visit('/form') - @xpath = Capybara::XPath.fillable_field('Name') + @xpath = XPath::HTML.fillable_field('Name') @session.find(@xpath).value.should == 'John Smith' end diff --git a/lib/capybara/xpath.rb b/lib/capybara/xpath.rb deleted file mode 100644 index 4af1360e..00000000 --- a/lib/capybara/xpath.rb +++ /dev/null @@ -1,127 +0,0 @@ -require 'xpath' - -module Capybara - - module XPath - - include ::XPath - extend self - - def from_css(css) - XPath::Union.new(*Nokogiri::CSS.xpath_for(css).map { |selector| ::XPath::Expression::Literal.new(:".#{selector}") }.flatten) - end - - def link(locator) - link = descendant(:a)[attr(:href)] - link[attr(:id).equals(locator) | text.is(locator) | attr(:title).is(locator) | descendant(:img)[attr(:alt).is(locator)]] - end - - def content(locator) - child(:"descendant-or-self::*")[current.n.contains(locator)] - end - - def button(locator) - button = descendant(:input)[attr(:type).one_of('submit', 'image', 'button')][attr(:id).equals(locator) | attr(:value).is(locator)] - button += descendant(:button)[attr(:id).equals(locator) | attr(:value).is(locator) | text.is(locator)] - button += descendant(:input)[attr(:type).equals('image')][attr(:alt).is(locator)] - end - - def link_or_button(locator) - link(locator) + button(locator) - end - - def fieldset(locator) - descendant(:fieldset)[attr(:id).equals(locator) | descendant(:legend)[text.is(locator)]] - end - - def field(locator, options={}) - if options[:with] - fillable_field(locator, options) - else - xpath = descendant(:input, :textarea, :select)[~attr(:type).one_of('submit', 'image', 'hidden')] - xpath = locate_field(xpath, locator) - xpath = xpath[attr(:checked)] if options[:checked] - xpath = xpath[~attr(:checked)] if options[:unchecked] - xpath - end - end - - def fillable_field(locator, options={}) - xpath = descendant(:input, :textarea)[~attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file')] - xpath = locate_field(xpath, locator) - xpath = xpath[field_value(options[:with])] if options.has_key?(:with) - xpath - end - - def select(locator, options={}) - xpath = locate_field(descendant(:select), locator) - - options[:options].each do |option| - xpath = xpath[descendant(:option).text.equals(option)] - end if options[:options] - - [options[:selected]].flatten.each do |option| - xpath = xpath[descendant(:option)[attr(:selected)].text.equals(option)] - end if options[:selected] - - xpath - end - - def checkbox(locator, options={}) - xpath = locate_field(descendant(:input)[attr(:type).equals('checkbox')], locator) - end - - def radio_button(locator, options={}) - locate_field(descendant(:input)[attr(:type).equals('radio')], locator) - end - - def file_field(locator, options={}) - locate_field(descendant(:input)[attr(:type).equals('file')], locator) - end - - def option(name) - descendant(:option)[text.n.is(name)] - end - - def table(locator, options={}) - xpath = descendant(:table)[attr(:id).equals(locator) | descendant(:caption).contains(locator)] - xpath = xpath[table_rows(options[:rows])] if options[:rows] - xpath - end - - def table_rows(rows) - row_conditions = descendant(:tr)[table_row(rows.first)] - rows.drop(1).each do |row| - row_conditions = row_conditions.next_sibling(:tr)[table_row(row)] - end - row_conditions - end - - def table_row(cells) - cell_conditions = child(:td, :th)[text.equals(cells.first)] - cells.drop(1).each do |cell| - cell_conditions = cell_conditions.next_sibling(:td, :th)[text.equals(cell)] - end - cell_conditions - end - - def wrap(path) - if path.respond_to?(:to_xpaths) - path.to_xpaths - else - [path.to_s].flatten - end - end - - protected - - def locate_field(xpath, locator) - locate_field = xpath[attr(:id).equals(locator) | attr(:name).equals(locator) | attr(:id).equals(anywhere(:label)[text.is(locator)].attr(:for))] - locate_field += descendant(:label)[text.is(locator)].descendant(xpath) - end - - def field_value(value) - (text.is(value) & name.equals('textarea')) | (attr(:value).equals(value) & ~name.equals('textarea')) - end - end -end