diff --git a/lib/webrat/core/locators.rb b/lib/webrat/core/locators.rb index dde4507..7a28944 100644 --- a/lib/webrat/core/locators.rb +++ b/lib/webrat/core/locators.rb @@ -62,6 +62,11 @@ module Webrat @session.elements[Webrat::XML.xpath_to(element)] end + def link_by_element(element) + return nil if element.nil? + @session.elements[Webrat::XML.xpath_to(element)] + end + def find_field_with_id(id, *field_types) #:nodoc: field_elements = Webrat::XML.xpath_search(dom, *Field.xpath_search) @@ -115,18 +120,10 @@ module Webrat end def find_link(text_or_title_or_id) #:nodoc: - # TODO - Convert to using elements - # - # matching_links = links.select do |possible_link| - # possible_link.matches_text?(text_or_title_or_id) || possible_link.matches_id?(text_or_title_or_id) - # end require "webrat/core/locators/link_locator" - if link = LinkLocator.new(self, text_or_title_or_id).locate - link - else - raise NotFoundError.new("Could not find link with text or title or id #{text_or_title_or_id.inspect}") - end + LinkLocator.new(self, text_or_title_or_id).locate || + raise(NotFoundError.new("Could not find link with text or title or id #{text_or_title_or_id.inspect}")) end def find_field_id_for_label(label_text) #:nodoc: diff --git a/lib/webrat/core/locators/link_locator.rb b/lib/webrat/core/locators/link_locator.rb index 702df31..f891a9c 100644 --- a/lib/webrat/core/locators/link_locator.rb +++ b/lib/webrat/core/locators/link_locator.rb @@ -6,15 +6,51 @@ class LinkLocator end def locate - matching_links = @scope.send(:links).select do |possible_link| - possible_link.matches_text?(@value) || possible_link.matches_id?(@value) + # TODO - Convert to using elements + + matching_links = link_elements.select do |link_element| + matches_text?(link_element) || + matches_id?(link_element) end if matching_links.any? - matching_links.min { |a, b| a.text.length <=> b.text.length } + link_element = matching_links.min { |a, b| Webrat::XML.inner_text(a).length <=> Webrat::XML.inner_text(b).length } + @scope.link_by_element(link_element) else nil end end + def matches_text?(link) + if @value.is_a?(Regexp) + matcher = @value + else + matcher = /#{Regexp.escape(@value.to_s)}/i + end + + replace_nbsp(Webrat::XML.inner_text(link)) =~ matcher || + replace_nbsp_ref(Webrat::XML.inner_html(link)) =~ matcher || + Webrat::XML.attribute(link, "title")=~ matcher + end + + def matches_id?(link) + if @value.is_a?(Regexp) + (Webrat::XML.attribute(link, "id") =~ @value) ? true : false + else + (Webrat::XML.attribute(link, "id") == @value) ? true : false + end + end + + def link_elements + Webrat::XML.css_search(@scope.dom, *Webrat::Link.css_search) + end + + def replace_nbsp(str) + str.gsub([0xA0].pack('U'), ' ') + end + + def replace_nbsp_ref(str) + str.gsub(' ',' ').gsub(' ', ' ') + end + end \ No newline at end of file diff --git a/lib/webrat/core/scope.rb b/lib/webrat/core/scope.rb index 62a58b6..cf83ec2 100644 --- a/lib/webrat/core/scope.rb +++ b/lib/webrat/core/scope.rb @@ -31,6 +31,7 @@ module Webrat forms # preload areas # preload + links # preload end # Verifies an input field or textarea exists on the current page, and stores a value for @@ -318,7 +319,9 @@ module Webrat def links #:nodoc: Webrat::XML.css_search(dom, Link.css_search).map do |element| - Link.new(@session, element) + link = Link.new(@session, element) + @session.elements[Webrat::XML.xpath_to(element)] = link + link end end